diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index 6d9a7a73f72db..ae4140c6bc594 100644 --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SMLoc.h" +#include "llvm/TargetParser/SubtargetFeature.h" #include #include #include @@ -410,6 +411,12 @@ class SystemZAsmParser : public MCTargetAsmParser { private: MCAsmParser &Parser; + + // A vector to contain the stack of FeatureBitsets created by `.machine push`. + // `.machine pop` pops the top of the stack and uses `setAvailableFeatures` to + // apply the result. + SmallVector MachineStack; + enum RegisterGroup { RegGR, RegFP, @@ -494,9 +501,8 @@ class SystemZAsmParser : public MCTargetAsmParser { public: SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) - : MCTargetAsmParser(Options, sti, MII), Parser(parser) { + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options, sti, MII), Parser(parser) { MCAsmParserExtension::Initialize(Parser); // Alias the .word directive to .short. @@ -1382,16 +1388,32 @@ bool SystemZAsmParser::parseDirectiveMachine(SMLoc L) { Parser.getTok().isNot(AsmToken::String)) return TokError("unexpected token in '.machine' directive"); - StringRef CPU = Parser.getTok().getIdentifier(); + StringRef Id = Parser.getTok().getIdentifier(); + SMLoc IdLoc = Parser.getTok().getLoc(); + Parser.Lex(); if (parseEOL()) return true; - MCSubtargetInfo &STI = copySTI(); - STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, ""); - setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); - - getTargetStreamer().emitMachine(CPU); + // Parse push and pop directives first + if (Id == "push") { + // Push the Current FeatureBitSet onto the stack. + MachineStack.push_back(getAvailableFeatures()); + } else if (Id == "pop") { + // If the stack is not empty pop the topmost FeatureBitset and use it. + if (MachineStack.empty()) + return Error(IdLoc, + "pop without corresponding push in '.machine' directive"); + setAvailableFeatures(MachineStack.back()); + MachineStack.pop_back(); + } else { + // Try to interpret the Identifier as a CPU spec and derive the + // FeatureBitset from that. + MCSubtargetInfo &STI = copySTI(); + STI.setDefaultFeatures(Id, /*TuneCPU*/ Id, ""); + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + } + getTargetStreamer().emitMachine(Id); return false; } diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h index 15617101fd08a..7e3c5f00525f4 100644 --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h @@ -54,7 +54,7 @@ class SystemZTargetStreamer : public MCTargetStreamer { void emitConstantPools() override; - virtual void emitMachine(StringRef CPU) {}; + virtual void emitMachine(StringRef CPUOrCommand) {}; virtual void emitExtern(StringRef Str) {}; @@ -85,7 +85,7 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer { class SystemZTargetELFStreamer : public SystemZTargetStreamer { public: SystemZTargetELFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {} - void emitMachine(StringRef CPU) override {} + void emitMachine(StringRef CPUOrCommand) override {} }; class SystemZTargetGNUStreamer : public SystemZTargetStreamer { @@ -94,8 +94,8 @@ class SystemZTargetGNUStreamer : public SystemZTargetStreamer { public: SystemZTargetGNUStreamer(MCStreamer &S, formatted_raw_ostream &OS) : SystemZTargetStreamer(S), OS(OS) {} - void emitMachine(StringRef CPU) override { - OS << "\t.machine " << CPU << "\n"; + void emitMachine(StringRef CPUOrCommand) override { + OS << "\t.machine " << CPUOrCommand << "\n"; } }; diff --git a/llvm/test/MC/SystemZ/machine-directive-invalid.s b/llvm/test/MC/SystemZ/machine-directive-invalid.s index 8b3147ecc62d4..262f11daeae8c 100644 --- a/llvm/test/MC/SystemZ/machine-directive-invalid.s +++ b/llvm/test/MC/SystemZ/machine-directive-invalid.s @@ -1,10 +1,17 @@ +// NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 # RUN: not llvm-mc -triple=s390x %s 2>&1 | FileCheck %s -# CHECK: [[#@LINE+1]]:9: error: unexpected token in '.machine' directive .machine +// CHECK: :[[@LINE-1]]:9: error: unexpected token in '.machine' directive + +.machine pop +// CHECK: :[[@LINE-1]]:10: error: pop without corresponding push in '.machine' directive + +.machine pop z13 +// CHECK: :[[@LINE-1]]:14: error: expected newline -# CHECK: [[#@LINE+1]]:10: error: unexpected token in '.machine' directive .machine 42 +// CHECK: :[[@LINE-1]]:10: error: unexpected token in '.machine' directive -# CHECK: [[#@LINE+1]]:13: error: expected newline .machine z13+ +// CHECK: :[[@LINE-1]]:13: error: expected newline diff --git a/llvm/test/MC/SystemZ/machine-directive.s b/llvm/test/MC/SystemZ/machine-directive.s index aa71c6aea5572..3c973ef1fade4 100644 --- a/llvm/test/MC/SystemZ/machine-directive.s +++ b/llvm/test/MC/SystemZ/machine-directive.s @@ -5,16 +5,20 @@ # CHECK: ^ # CHECK-NOT: error: +# CHECK: .machine push # CHECK: .machine z13 # CHECK: vgbm %v0, 0 # CHECK: .machine zEC12 -# CHECK: .machine z13 +# CHECK: .machine pop # CHECK: vgbm %v0, 3 +# CHECK: .machine pop +.machine push .machine z13 +.machine push vgbm %v0, 0 .machine zEC12 vgbm %v0, 1 -.machine z13 +.machine pop vgbm %v0, 3 - +.machine pop