diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -9,6 +9,7 @@ #include "MCTargetDesc/SystemZInstPrinter.h" #include "MCTargetDesc/SystemZMCAsmInfo.h" #include "MCTargetDesc/SystemZMCTargetDesc.h" +#include "SystemZTargetStreamer.h" #include "TargetInfo/SystemZTargetInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -405,6 +406,13 @@ SMLoc StartLoc, EndLoc; }; + SystemZTargetStreamer &getTargetStreamer() { + assert(getParser().getStreamer().getTargetStreamer() && + "do not have a target streamer"); + MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); + return static_cast(TS); + } + bool parseRegister(Register &Reg, bool RestoreOnFailure = false); bool parseIntegerRegister(Register &Reg, RegisterGroup Group); @@ -420,6 +428,7 @@ bool parseAddressRegister(Register &Reg); bool ParseDirectiveInsn(SMLoc L); + bool ParseDirectiveMachine(SMLoc L); OperandMatchResultTy parseAddress(OperandVector &Operands, MemoryKind MemKind, @@ -1210,6 +1219,8 @@ if (IDVal == ".insn") return ParseDirectiveInsn(DirectiveID.getLoc()); + if (IDVal == ".machine") + return ParseDirectiveMachine(DirectiveID.getLoc()); return true; } @@ -1322,6 +1333,28 @@ return false; } +/// ParseDirectiveMachine +/// ::= .machine [ mcpu ] +bool SystemZAsmParser::ParseDirectiveMachine(SMLoc L) { + MCAsmParser &Parser = getParser(); + if (Parser.getTok().isNot(AsmToken::Identifier) && + Parser.getTok().isNot(AsmToken::String)) + return Error(L, "unexpected token in '.machine' directive"); + + StringRef CPU = Parser.getTok().getIdentifier(); + Parser.Lex(); + if (parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix(" in '.machine' directive"); + + MCSubtargetInfo &STI = copySTI(); + STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + + getTargetStreamer().emitMachine(CPU); + + return false; +} + bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, bool RestoreOnFailure) { Register Reg; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -9,6 +9,7 @@ #include "SystemZMCTargetDesc.h" #include "SystemZInstPrinter.h" #include "SystemZMCAsmInfo.h" +#include "SystemZTargetStreamer.h" #include "TargetInfo/SystemZTargetInfo.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCInstrInfo.h" @@ -182,6 +183,38 @@ return new SystemZInstPrinter(MAI, MII, MRI); } +namespace { +class SystemZTargetAsmStreamer : public SystemZTargetStreamer { + formatted_raw_ostream &OS; + +public: + SystemZTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) + : SystemZTargetStreamer(S), OS(OS) {} + void emitMachine(StringRef CPU) override { + OS << "\t.machine " << CPU << "\n"; + } +}; + +class SystemZTargetELFStreamer : public SystemZTargetStreamer { +public: + SystemZTargetELFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {} + void emitMachine(StringRef CPU) override {} +}; +} // end namespace + +static MCTargetStreamer * +createAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new SystemZTargetAsmStreamer(S, OS); +} + +static MCTargetStreamer * +createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { + return new SystemZTargetELFStreamer(S); +} + extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTargetMC() { // Register the MCAsmInfo. TargetRegistry::RegisterMCAsmInfo(getTheSystemZTarget(), @@ -210,4 +243,12 @@ // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(getTheSystemZTarget(), createSystemZMCInstPrinter); + + // Register the asm streamer. + TargetRegistry::RegisterAsmTargetStreamer(getTheSystemZTarget(), + createAsmTargetStreamer); + + // Register the obj streamer + TargetRegistry::RegisterObjectTargetStreamer(getTheSystemZTarget(), + createObjectTargetStreamer); } diff --git a/llvm/lib/Target/SystemZ/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/SystemZTargetStreamer.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/SystemZ/SystemZTargetStreamer.h @@ -0,0 +1,26 @@ +//=- SystemZTargetStreamer.h - SystemZ Target Streamer ----------*- 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_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H +#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCStreamer.h" + +namespace llvm { + +class SystemZTargetStreamer : public MCTargetStreamer { +public: + SystemZTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + + virtual void emitMachine(StringRef CPU) = 0; +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H diff --git a/llvm/test/MC/SystemZ/machine-directive.s b/llvm/test/MC/SystemZ/machine-directive.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/SystemZ/machine-directive.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc -triple=s390x-linux-gnu %s --filetype=asm 2>&1 | FileCheck %s + +# CHECK: error: instruction requires: vector +# CHECK: vgbm %v0, 1 +# CHECK: ^ + +# CHECK-NOT: error: +# CHECK: .machine z13 +# CHECK: vgbm %v0, 0 +# CHECK: .machine zEC12 +# CHECK: .machine z13 +# CHECK: vgbm %v0, 3 + +.machine z13 +vgbm %v0, 0 +.machine zEC12 +vgbm %v0, 1 +.machine z13 +vgbm %v0, 3 +