[llvm] af20c1c - [MC] Add three-state parseDirective as a replacement for ParseDirective

Sergei Barannikov via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 30 18:33:38 PDT 2023


Author: Sergei Barannikov
Date: 2023-07-01T04:33:28+03:00
New Revision: af20c1c1298d15f36470cd9d5b2cccb3b9b59c30

URL: https://github.com/llvm/llvm-project/commit/af20c1c1298d15f36470cd9d5b2cccb3b9b59c30
DIFF: https://github.com/llvm/llvm-project/commit/af20c1c1298d15f36470cd9d5b2cccb3b9b59c30.diff

LOG: [MC] Add three-state parseDirective as a replacement for ParseDirective

Conventionally, parsing methods return false on success and true on
error. However, directive parsing methods need a third state: the
directive is not target specific. AsmParser::parseStatement detected
this case by using a fragile heuristic: if the target parser did not
consume any tokens, the directive is assumed to be not target-specific.

Some targets fail to follow the convention: they return success after
emitting an error or do not consume the entire line and return failure
on successful parsing. This was partially worked around by checking for
pending errors in parseStatement.

This patch tries to improve the situation by introducing parseDirective
method that returns ParseStatus -- three-state class. The new method
should eventually replace the old one returning bool.

ParseStatus is intentionally implicitly constructible from bool to allow
uses like `return Error(Loc, "message")`. It also has a potential to
replace OperandMatchResulTy as it is more convenient to use due to the
implicit construction from bool and more type safe.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D154101

Added: 
    llvm/test/MC/MSP430/directive-byte-word-long-invalid.s
    llvm/test/MC/MSP430/refsym-invalid.s
    llvm/test/MC/SystemZ/gnu-attributes-invalid.s
    llvm/test/MC/SystemZ/machine-directive-invalid.s
    llvm/test/MC/WebAssembly/export-name-invalid.s
    llvm/test/MC/WebAssembly/functype-invalid.s
    llvm/test/MC/WebAssembly/globaltype-invalid.s
    llvm/test/MC/WebAssembly/import-module-invalid.s
    llvm/test/MC/WebAssembly/import-name-invalid.s
    llvm/test/MC/WebAssembly/tabletype-invalid.s
    llvm/test/MC/WebAssembly/tagtype-invalid.s

Modified: 
    llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
    llvm/lib/MC/MCParser/AsmParser.cpp
    llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
    llvm/lib/MC/MCParser/MasmParser.cpp
    llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
    llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
    llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
    llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
    llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
    llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
    llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
    llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
    llvm/test/MC/CSKY/invalid-attribute.s
    llvm/test/MC/Sparc/sparc-directives.s
    llvm/test/MC/VE/data-size-error.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 6a060f3f63f330..299f9b055ff779 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -122,6 +122,32 @@ struct ParseInstructionInfo {
     : AsmRewrites(rewrites) {}
 };
 
+/// Ternary parse status returned by various parse* methods.
+class ParseStatus {
+  enum class StatusTy { Success, Failure, NoMatch } Status;
+
+public:
+#if __cplusplus >= 202002L
+  using enum StatusTy;
+#else
+  static constexpr StatusTy Success = StatusTy::Success;
+  static constexpr StatusTy Failure = StatusTy::Failure;
+  static constexpr StatusTy NoMatch = StatusTy::NoMatch;
+#endif
+
+  constexpr ParseStatus() : Status(NoMatch) {}
+
+  constexpr ParseStatus(StatusTy Status) : Status(Status) {}
+
+  constexpr ParseStatus(bool Error) : Status(Error ? Failure : Success) {}
+
+  template <typename T> constexpr ParseStatus(T) = delete;
+
+  constexpr bool isSuccess() const { return Status == StatusTy::Success; }
+  constexpr bool isFailure() const { return Status == StatusTy::Failure; }
+  constexpr bool isNoMatch() const { return Status == StatusTy::NoMatch; }
+};
+
 enum OperandMatchResultTy {
   MatchOperand_Success,  // operand matched successfully
   MatchOperand_NoMatch,  // operand did not match
@@ -408,6 +434,7 @@ class MCTargetAsmParser : public MCAsmParserExtension {
   }
 
   /// ParseDirective - Parse a target specific assembler directive
+  /// This method is deprecated, use 'parseDirective' instead.
   ///
   /// The parser is positioned following the directive name.  The target
   /// specific directive parser should parse the entire directive doing or
@@ -417,7 +444,19 @@ class MCTargetAsmParser : public MCAsmParserExtension {
   /// end-of-statement token and false is returned.
   ///
   /// \param DirectiveID - the identifier token of the directive.
-  virtual bool ParseDirective(AsmToken DirectiveID) = 0;
+  virtual bool ParseDirective(AsmToken DirectiveID) { return true; }
+
+  /// Parses a target-specific assembler directive.
+  ///
+  /// The parser is positioned following the directive name. The target-specific
+  /// directive parser should parse the entire directive doing or recording any
+  /// target-specific work, or emit an error. On success, the entire line should
+  /// be parsed up to and including the end-of-statement token. On failure, the
+  /// parser is not required to read to the end of the line. If the directive is
+  /// not target-specific, no tokens should be consumed and NoMatch is returned.
+  ///
+  /// \param DirectiveID - The token identifying the directive.
+  virtual ParseStatus parseDirective(AsmToken DirectiveID);
 
   /// MatchAndEmitInstruction - Recognize a series of operands of a parsed
   /// instruction as an actual MCInst and emit it to the specified MCStreamer.

diff  --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 2c81c33c92d538..04590ed57a9f20 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -1999,20 +1999,12 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
 
     getTargetParser().flushPendingInstructions(getStreamer());
 
-    SMLoc StartTokLoc = getTok().getLoc();
-    bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
-
-    if (hasPendingError())
-      return true;
-    // Currently the return value should be true if we are
-    // uninterested but as this is at odds with the standard parsing
-    // convention (return true = error) we have instances of a parsed
-    // directive that fails returning true as an error. Catch these
-    // cases as best as possible errors here.
-    if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
+    ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
+    assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
+           "Should only return Failure iff there was an error");
+    if (TPDirectiveReturn.isFailure())
       return true;
-    // Return if we did some parsing or believe we succeeded.
-    if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
+    if (TPDirectiveReturn.isSuccess())
       return false;
 
     // Next, check the extension directive map to see if any extension has

diff  --git a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
index 940f26d4750b43..0db5fb36f79508 100644
--- a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp
@@ -27,3 +27,24 @@ MCSubtargetInfo &MCTargetAsmParser::copySTI() {
 const MCSubtargetInfo &MCTargetAsmParser::getSTI() const {
   return *STI;
 }
+
+ParseStatus MCTargetAsmParser::parseDirective(AsmToken DirectiveID) {
+  SMLoc StartTokLoc = getTok().getLoc();
+  // Delegate to ParseDirective by default for transition period. Once the
+  // transition is over, this method should just return NoMatch.
+  bool Res = ParseDirective(DirectiveID);
+
+  // Some targets erroneously report success after emitting an error.
+  if (getParser().hasPendingError())
+    return ParseStatus::Failure;
+
+  // ParseDirective returns true if there was an error or if the directive is
+  // not target-specific. Disambiguate the two cases by comparing position of
+  // the lexer before and after calling the method: if no tokens were consumed,
+  // there was no match, otherwise there was a failure.
+  if (!Res)
+    return ParseStatus::Success;
+  if (getTok().getLoc() != StartTokLoc)
+    return ParseStatus::Failure;
+  return ParseStatus::NoMatch;
+}

diff  --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index d41df71edbdfad..307256ffaf456b 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -2304,21 +2304,15 @@ bool MasmParser::parseStatement(ParseStatementInfo &Info,
       return (*Handler.second)(Handler.first, IDVal, IDLoc);
 
     // Next, let the target-specific assembly parser try.
-    SMLoc StartTokLoc = getTok().getLoc();
-    bool TPDirectiveReturn =
-        ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID);
+    if (ID.isNot(AsmToken::Identifier))
+      return false;
 
-    if (hasPendingError())
-      return true;
-    // Currently the return value should be true if we are
-    // uninterested but as this is at odds with the standard parsing
-    // convention (return true = error) we have instances of a parsed
-    // directive that fails returning true as an error. Catch these
-    // cases as best as possible errors here.
-    if (TPDirectiveReturn && StartTokLoc != getTok().getLoc())
+    ParseStatus TPDirectiveReturn = getTargetParser().parseDirective(ID);
+    assert(TPDirectiveReturn.isFailure() == hasPendingError() &&
+           "Should only return Failure iff there was an error");
+    if (TPDirectiveReturn.isFailure())
       return true;
-    // Return if we did some parsing or believe we succeeded.
-    if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc())
+    if (TPDirectiveReturn.isSuccess())
       return false;
 
     // Finally, if no one else is interested in this directive, it must be

diff  --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
index 8d30b7886040f3..6c328ffc58a466 100644
--- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
+++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
@@ -64,7 +64,7 @@ class AVRAsmParser : public MCTargetAsmParser {
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   OperandMatchResultTy parseMemriOperand(OperandVector &Operands);
 
@@ -90,7 +90,7 @@ class AVRAsmParser : public MCTargetAsmParser {
                       uint64_t const &ErrorInfo);
   bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo);
 
-  bool parseLiteralValues(unsigned SizeInBytes, SMLoc L);
+  ParseStatus parseLiteralValues(unsigned SizeInBytes, SMLoc L);
 
 public:
   AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
@@ -674,19 +674,18 @@ bool AVRAsmParser::ParseInstruction(ParseInstructionInfo &Info,
   return false;
 }
 
-bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID) {
+ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getIdentifier();
-  if (IDVal.lower() == ".long") {
-    parseLiteralValues(SIZE_LONG, DirectiveID.getLoc());
-  } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") {
-    parseLiteralValues(SIZE_WORD, DirectiveID.getLoc());
-  } else if (IDVal.lower() == ".byte") {
-    parseLiteralValues(1, DirectiveID.getLoc());
-  }
-  return true;
+  if (IDVal.lower() == ".long")
+    return parseLiteralValues(SIZE_LONG, DirectiveID.getLoc());
+  if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
+    return parseLiteralValues(SIZE_WORD, DirectiveID.getLoc());
+  if (IDVal.lower() == ".byte")
+    return parseLiteralValues(1, DirectiveID.getLoc());
+  return ParseStatus::NoMatch;
 }
 
-bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
+ParseStatus AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
   MCAsmParser &Parser = getParser();
   AVRMCELFStreamer &AVRStreamer =
       static_cast<AVRMCELFStreamer &>(Parser.getStreamer());
@@ -698,7 +697,7 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
     MCSymbol *Symbol = getContext().getOrCreateSymbol(".text");
     AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L,
                                         AVRMCExpr::VK_AVR_None);
-    return false;
+    return ParseStatus::NoMatch;
   }
 
   if (Parser.getTok().getKind() == AsmToken::Identifier &&
@@ -715,7 +714,10 @@ bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
     MCSymbol *Symbol =
         getContext().getOrCreateSymbol(Parser.getTok().getString());
     AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L, ModifierKind);
-    return false;
+    Lex(); // Eat the symbol name.
+    if (parseToken(AsmToken::RParen))
+      return ParseStatus::Failure;
+    return parseEOL();
   }
 
   auto parseOne = [&]() -> bool {

diff  --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index 85858b74ba80e2..9896ddd15fc159 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -47,7 +47,7 @@ class BPFAsmParser : public MCTargetAsmParser {
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   // "=" is used as assignment operator for assembly statment, so can't be used
   // for symbol assignment.
@@ -516,7 +516,9 @@ bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
   return false;
 }
 
-bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+ParseStatus BPFAsmParser::parseDirective(AsmToken DirectiveID) {
+  return ParseStatus::NoMatch;
+}
 
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmParser() {
   RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());

diff  --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
index 413c331f1c3a2b..c4d600757d811e 100644
--- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
+++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
@@ -77,7 +77,7 @@ class CSKYAsmParser : public MCTargetAsmParser {
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   // Helper to actually emit an instruction to the MCStreamer. Also, when
   // possible, compression of the instruction is performed.
@@ -1573,17 +1573,13 @@ OperandMatchResultTy CSKYAsmParser::tryParseRegister(MCRegister &RegNo,
   return MatchOperand_Success;
 }
 
-bool CSKYAsmParser::ParseDirective(AsmToken DirectiveID) {
-  // This returns false if this function recognizes the directive
-  // regardless of whether it is successfully handles or reports an
-  // error. Otherwise it returns true to give the generic parser a
-  // chance at recognizing it.
+ParseStatus CSKYAsmParser::parseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getString();
 
   if (IDVal == ".csky_attribute")
     return parseDirectiveAttribute();
 
-  return true;
+  return ParseStatus::NoMatch;
 }
 
 /// parseDirectiveAttribute
@@ -1597,10 +1593,8 @@ bool CSKYAsmParser::parseDirectiveAttribute() {
     StringRef Name = Parser.getTok().getIdentifier();
     std::optional<unsigned> Ret =
         ELFAttrs::attrTypeFromString(Name, CSKYAttrs::getCSKYAttributeTags());
-    if (!Ret) {
-      Error(TagLoc, "attribute name not recognised: " + Name);
-      return false;
-    }
+    if (!Ret)
+      return Error(TagLoc, "attribute name not recognised: " + Name);
     Tag = *Ret;
     Parser.Lex();
   } else {
@@ -1611,8 +1605,8 @@ bool CSKYAsmParser::parseDirectiveAttribute() {
       return true;
 
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
-    if (check(!CE, TagLoc, "expected numeric constant"))
-      return true;
+    if (!CE)
+      return Error(TagLoc, "expected numeric constant");
 
     Tag = CE->getValue();
   }

diff  --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
index 2c7013dd492e06..cf84e865974eab 100644
--- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
+++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
@@ -62,7 +62,7 @@ class LanaiAsmParser : public MCTargetAsmParser {
 
   bool parsePrePost(StringRef Type, int *OffsetValue);
 
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -649,7 +649,9 @@ struct LanaiOperand : public MCParsedAsmOperand {
 
 } // end anonymous namespace
 
-bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }
+ParseStatus LanaiAsmParser::parseDirective(AsmToken DirectiveID) {
+  return ParseStatus::NoMatch;
+}
 
 bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
                                              OperandVector &Operands,

diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index a28e9e5efc954e..d3f4551664850b 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -51,7 +51,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
-  bool ParseDirective(AsmToken DirectiveID) override { return true; }
+  ParseStatus parseDirective(AsmToken DirectiveID) override {
+    return ParseStatus::NoMatch;
+  }
 
   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                OperandVector &Operands, MCStreamer &Out,

diff  --git a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
index 89a5f02528ccdd..1d9b5055dd7916 100644
--- a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
+++ b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp
@@ -72,7 +72,7 @@ class M68kAsmParser : public MCTargetAsmParser {
                                         SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
                                OperandVector &Operands, MCStreamer &Out,
                                uint64_t &ErrorInfo,
@@ -992,7 +992,9 @@ bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
   return false;
 }
 
-bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+ParseStatus M68kAsmParser::parseDirective(AsmToken DirectiveID) {
+  return ParseStatus::NoMatch;
+}
 
 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
                                    OperandVector const &Operands,

diff  --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
index 1389f0a76888ba..f2c90f56586350 100644
--- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
+++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
@@ -53,7 +53,7 @@ class MSP430AsmParser : public MCTargetAsmParser {
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
 
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
   bool ParseDirectiveRefSym(AsmToken DirectiveID);
 
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
@@ -424,27 +424,26 @@ bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
 }
 
 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
-    StringRef Name;
-    if (getParser().parseIdentifier(Name))
-      return TokError("expected identifier in directive");
+  StringRef Name;
+  if (getParser().parseIdentifier(Name))
+    return TokError("expected identifier in directive");
 
-    MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-    getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
-    return false;
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+  getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
+  return parseEOL();
 }
 
-bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) {
+ParseStatus MSP430AsmParser::parseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getIdentifier();
-  if (IDVal.lower() == ".long") {
-    ParseLiteralValues(4, DirectiveID.getLoc());
-  } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") {
-    ParseLiteralValues(2, DirectiveID.getLoc());
-  } else if (IDVal.lower() == ".byte") {
-    ParseLiteralValues(1, DirectiveID.getLoc());
-  } else if (IDVal.lower() == ".refsym") {
+  if (IDVal.lower() == ".long")
+    return ParseLiteralValues(4, DirectiveID.getLoc());
+  if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
+    return ParseLiteralValues(2, DirectiveID.getLoc());
+  if (IDVal.lower() == ".byte")
+    return ParseLiteralValues(1, DirectiveID.getLoc());
+  if (IDVal.lower() == ".refsym")
     return ParseDirectiveRefSym(DirectiveID);
-  }
-  return true;
+  return ParseStatus::NoMatch;
 }
 
 bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {

diff  --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index 6306fd186d9e3a..9bfee26db806d4 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -76,7 +76,7 @@ class SparcAsmParser : public MCTargetAsmParser {
                                         SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
@@ -769,25 +769,23 @@ bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
   return false;
 }
 
-bool SparcAsmParser::
-ParseDirective(AsmToken DirectiveID)
-{
+ParseStatus SparcAsmParser::parseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getString();
 
   if (IDVal == ".register") {
     // For now, ignore .register directive.
     Parser.eatToEndOfStatement();
-    return false;
+    return ParseStatus::Success;
   }
   if (IDVal == ".proc") {
     // For compatibility, ignore this directive.
     // (It's supposed to be an "optimization" in the Sun assembler)
     Parser.eatToEndOfStatement();
-    return false;
+    return ParseStatus::Success;
   }
 
   // Let the MC layer to handle other directives.
-  return true;
+  return ParseStatus::NoMatch;
 }
 
 OperandMatchResultTy

diff  --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
index 61831cc50de38d..4f8d16b501b845 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -494,7 +494,7 @@ class SystemZAsmParser : public MCTargetAsmParser {
   }
 
   // Override MCTargetAsmParser.
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
   bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
                      SMLoc &EndLoc) override;
   bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
@@ -1219,7 +1219,7 @@ SystemZAsmParser::parseAddress(OperandVector &Operands, MemoryKind MemKind,
   return MatchOperand_Success;
 }
 
-bool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) {
+ParseStatus SystemZAsmParser::parseDirective(AsmToken DirectiveID) {
   StringRef IDVal = DirectiveID.getIdentifier();
 
   if (IDVal == ".insn")
@@ -1229,7 +1229,7 @@ bool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) {
   if (IDVal.startswith(".gnu_attribute"))
     return ParseGNUAttribute(DirectiveID.getLoc());
 
-  return true;
+  return ParseStatus::NoMatch;
 }
 
 /// ParseDirectiveInsn
@@ -1346,12 +1346,12 @@ 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");
+    return TokError("unexpected token in '.machine' directive");
 
   StringRef CPU = Parser.getTok().getIdentifier();
   Parser.Lex();
-  if (parseToken(AsmToken::EndOfStatement))
-    return addErrorSuffix(" in '.machine' directive");
+  if (parseEOL())
+    return true;
 
   MCSubtargetInfo &STI = copySTI();
   STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");
@@ -1366,18 +1366,15 @@ bool SystemZAsmParser::ParseGNUAttribute(SMLoc L) {
   int64_t Tag;
   int64_t IntegerValue;
   if (!Parser.parseGNUAttribute(L, Tag, IntegerValue))
-    return false;
+    return Error(L, "malformed .gnu_attribute directive");
 
   // Tag_GNU_S390_ABI_Vector tag is '8' and can be 0, 1, or 2.
-  if (Tag != 8 || (IntegerValue < 0 || IntegerValue > 2)) {
-    Error(Parser.getTok().getLoc(),
-          "Unrecognized .gnu_attribute tag/value pair.");
-    return false;
-  }
+  if (Tag != 8 || (IntegerValue < 0 || IntegerValue > 2))
+    return Error(L, "unrecognized .gnu_attribute tag/value pair.");
 
   Parser.getStreamer().emitGNUAttribute(Tag, IntegerValue);
 
-  return true;
+  return parseEOL();
 }
 
 bool SystemZAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,

diff  --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
index 0a72f29659b041..a9cedf1dd97c39 100644
--- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -62,7 +62,7 @@ class VEAsmParser : public MCTargetAsmParser {
                                         SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
 
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
@@ -998,7 +998,7 @@ bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
   return false;
 }
 
-bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
+ParseStatus VEAsmParser::parseDirective(AsmToken DirectiveID) {
   std::string IDVal = DirectiveID.getIdentifier().lower();
 
   // Defines VE specific directives.  Reference is "Vector Engine Assembly
@@ -1018,7 +1018,7 @@ bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
     return parseLiteralValues(8, DirectiveID.getLoc());
 
   // Let the MC layer to handle other directives.
-  return true;
+  return ParseStatus::NoMatch;
 }
 
 /// parseLiteralValues

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index e8efb5582c9434..1e2d3888fe1c15 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -785,31 +785,23 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
   // This function processes wasm-specific directives streamed to
   // WebAssemblyTargetStreamer, all others go to the generic parser
   // (see WasmAsmParser).
-  bool ParseDirective(AsmToken DirectiveID) override {
-    // This function has a really weird return value behavior that is 
diff erent
-    // from all the other parsing functions:
-    // - return true && no tokens consumed -> don't know this directive / let
-    //   the generic parser handle it.
-    // - return true && tokens consumed -> a parsing error occurred.
-    // - return false -> processed this directive successfully.
+  ParseStatus parseDirective(AsmToken DirectiveID) override {
     assert(DirectiveID.getKind() == AsmToken::Identifier);
     auto &Out = getStreamer();
     auto &TOut =
         reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
     auto &Ctx = Out.getContext();
 
-    // TODO: any time we return an error, at least one token must have been
-    // consumed, otherwise this will not signal an error to the caller.
     if (DirectiveID.getString() == ".globaltype") {
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       if (expect(AsmToken::Comma, ","))
-        return true;
+        return ParseStatus::Failure;
       auto TypeTok = Lexer.getTok();
       auto TypeName = expectIdent();
       if (TypeName.empty())
-        return true;
+        return ParseStatus::Failure;
       auto Type = WebAssembly::parseType(TypeName);
       if (!Type)
         return error("Unknown type in .globaltype directive: ", TypeTok);
@@ -820,6 +812,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       if (isNext(AsmToken::Comma)) {
         TypeTok = Lexer.getTok();
         auto Id = expectIdent();
+        if (Id.empty())
+          return ParseStatus::Failure;
         if (Id == "immutable")
           Mutable = false;
         else
@@ -839,14 +833,14 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       if (expect(AsmToken::Comma, ","))
-        return true;
+        return ParseStatus::Failure;
 
       auto ElemTypeTok = Lexer.getTok();
       auto ElemTypeName = expectIdent();
       if (ElemTypeName.empty())
-        return true;
+        return ParseStatus::Failure;
       std::optional<wasm::ValType> ElemType =
           WebAssembly::parseType(ElemTypeName);
       if (!ElemType)
@@ -854,7 +848,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
 
       wasm::WasmLimits Limits = DefaultLimits();
       if (isNext(AsmToken::Comma) && parseLimits(&Limits))
-        return true;
+        return ParseStatus::Failure;
 
       // Now that we have the name and table type, we can actually create the
       // symbol
@@ -874,7 +868,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       // parses the locals separately.
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
       if (WasmSym->isDefined()) {
         // We push 'Function' either when a label is parsed or a .functype
@@ -890,7 +884,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         if (CurrentState != FunctionLabel) {
           // This .functype indicates a start of a function.
           if (ensureEmptyNestingStack())
-            return true;
+            return ParseStatus::Failure;
           push(Function);
         }
         CurrentState = FunctionStart;
@@ -898,7 +892,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       }
       auto Signature = std::make_unique<wasm::WasmSignature>();
       if (parseSignature(Signature.get()))
-        return true;
+        return ParseStatus::Failure;
       TC.funcDecl(*Signature);
       WasmSym->setSignature(Signature.get());
       addSignature(std::move(Signature));
@@ -911,47 +905,56 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     if (DirectiveID.getString() == ".export_name") {
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       if (expect(AsmToken::Comma, ","))
-        return true;
+        return ParseStatus::Failure;
       auto ExportName = expectIdent();
+      if (ExportName.empty())
+        return ParseStatus::Failure;
       auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
       WasmSym->setExportName(storeName(ExportName));
       TOut.emitExportName(WasmSym, ExportName);
+      return expect(AsmToken::EndOfStatement, "EOL");
     }
 
     if (DirectiveID.getString() == ".import_module") {
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       if (expect(AsmToken::Comma, ","))
-        return true;
+        return ParseStatus::Failure;
       auto ImportModule = expectIdent();
+      if (ImportModule.empty())
+        return ParseStatus::Failure;
       auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
       WasmSym->setImportModule(storeName(ImportModule));
       TOut.emitImportModule(WasmSym, ImportModule);
+      return expect(AsmToken::EndOfStatement, "EOL");
     }
 
     if (DirectiveID.getString() == ".import_name") {
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       if (expect(AsmToken::Comma, ","))
-        return true;
+        return ParseStatus::Failure;
       auto ImportName = expectIdent();
+      if (ImportName.empty())
+        return ParseStatus::Failure;
       auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
       WasmSym->setImportName(storeName(ImportName));
       TOut.emitImportName(WasmSym, ImportName);
+      return expect(AsmToken::EndOfStatement, "EOL");
     }
 
     if (DirectiveID.getString() == ".tagtype") {
       auto SymName = expectIdent();
       if (SymName.empty())
-        return true;
+        return ParseStatus::Failure;
       auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
       auto Signature = std::make_unique<wasm::WasmSignature>();
       if (parseRegTypeList(Signature->Params))
-        return true;
+        return ParseStatus::Failure;
       WasmSym->setSignature(Signature.get());
       addSignature(std::move(Signature));
       WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
@@ -966,7 +969,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
                      Lexer.getTok());
       SmallVector<wasm::ValType, 4> Locals;
       if (parseRegTypeList(Locals))
-        return true;
+        return ParseStatus::Failure;
       TC.localDecl(Locals);
       TOut.emitLocal(Locals);
       CurrentState = FunctionLocals;
@@ -978,7 +981,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         DirectiveID.getString() == ".int32" ||
         DirectiveID.getString() == ".int64") {
       if (CheckDataSection())
-        return true;
+        return ParseStatus::Failure;
       const MCExpr *Val;
       SMLoc End;
       if (Parser.parseExpression(Val, End))
@@ -991,7 +994,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
 
     if (DirectiveID.getString() == ".asciz") {
       if (CheckDataSection())
-        return true;
+        return ParseStatus::Failure;
       std::string S;
       if (Parser.parseEscapedString(S))
         return error("Cannot parse string constant: ", Lexer.getTok());
@@ -999,7 +1002,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       return expect(AsmToken::EndOfStatement, "EOL");
     }
 
-    return true; // We didn't process this directive.
+    return ParseStatus::NoMatch; // We didn't process this directive.
   }
 
   // Called either when the first instruction is parsed of the function ends.

diff  --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
index b8632d4ababf6e..39998ff2a41117 100644
--- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
+++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
@@ -36,7 +36,7 @@ class XtensaAsmParser : public MCTargetAsmParser {
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
 
   // Override MCTargetAsmParser.
-  bool ParseDirective(AsmToken DirectiveID) override;
+  ParseStatus parseDirective(AsmToken DirectiveID) override;
   bool parseRegister(MCRegister &RegNo,
                      SMLoc &StartLoc, SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
@@ -697,7 +697,9 @@ bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
   return false;
 }
 
-bool XtensaAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {
+  return ParseStatus::NoMatch;
+}
 
 // Force static initialization.
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {

diff  --git a/llvm/test/MC/CSKY/invalid-attribute.s b/llvm/test/MC/CSKY/invalid-attribute.s
index a6558e75f82a1c..7123d8f6a7c860 100644
--- a/llvm/test/MC/CSKY/invalid-attribute.s
+++ b/llvm/test/MC/CSKY/invalid-attribute.s
@@ -5,6 +5,21 @@
 
 # RUN: not llvm-mc %s -triple=csky -filetype=asm 2>&1 | FileCheck %s
 
+.csky_attribute CSKY_UNKNOWN
+# CHECK: [[@LINE-1]]:17: error: attribute name not recognised: CSKY_UNKNOWN
+
+.csky_attribute CSKY_ARCH_NAME
+# CHECK: [[@LINE-1]]:31: error: expected comma
+
+.csky_attribute CSKY_ISA_FLAGS
+# CHECK: [[@LINE-1]]:31: error: expected comma
+
+.csky_attribute CSKY_ARCH_NAME, "foo",
+# CHECK: [[@LINE-1]]:38: error: expected newline
+
+.csky_attribute CSKY_ISA_FLAGS, 42,
+# CHECK: [[@LINE-1]]:35: error: expected newline
+
 .csky_attribute CSKY_ARCH_NAME, "foo"
 # CHECK: [[@LINE-1]]:33: error: unknown arch name 
 

diff  --git a/llvm/test/MC/MSP430/directive-byte-word-long-invalid.s b/llvm/test/MC/MSP430/directive-byte-word-long-invalid.s
new file mode 100644
index 00000000000000..c70fb48443c560
--- /dev/null
+++ b/llvm/test/MC/MSP430/directive-byte-word-long-invalid.s
@@ -0,0 +1,22 @@
+# RUN: not llvm-mc -triple=msp430 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+3]]:6: error: unknown token in expression
+# CHECK: [[#@LINE+3]]:6: error: unknown token in expression
+# CHECK: [[#@LINE+3]]:6: error: unknown token in expression
+.byte, 42
+.word, 42
+.long, 42
+
+# CHECK: [[#@LINE+3]]:10: error: unknown token in expression
+# CHECK: [[#@LINE+3]]:10: error: unknown token in expression
+# CHECK: [[#@LINE+3]]:10: error: unknown token in expression
+.byte 42,
+.word 42,
+.long 42,
+
+# CHECK: [[#@LINE+3]]:10: error: unexpected token
+# CHECK: [[#@LINE+3]]:10: error: unexpected token
+# CHECK: [[#@LINE+3]]:10: error: unexpected token
+.byte 42 42
+.word 42 42
+.long 42 42

diff  --git a/llvm/test/MC/MSP430/refsym-invalid.s b/llvm/test/MC/MSP430/refsym-invalid.s
new file mode 100644
index 00000000000000..5cbf707870e87d
--- /dev/null
+++ b/llvm/test/MC/MSP430/refsym-invalid.s
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc -triple=msp430 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:8: error: expected identifier in directive
+.refsym
+
+# CHECK: [[#@LINE+1]]:9: error: expected identifier in directive
+.refsym 42
+
+# CHECK: [[#@LINE+1]]:12: error: expected newline
+.refsym sym,

diff  --git a/llvm/test/MC/Sparc/sparc-directives.s b/llvm/test/MC/Sparc/sparc-directives.s
index 5c8cd004d5777d..1e1ce740c11d09 100644
--- a/llvm/test/MC/Sparc/sparc-directives.s
+++ b/llvm/test/MC/Sparc/sparc-directives.s
@@ -3,7 +3,10 @@
 
         ! '.proc' is documented to do nothing in the binutils assembler.
         ! so it should do nothing for clang either, i.e. not be an error.
-        .proc 1
+        .proc 1 x (
+
+        ! '.register' is currently ignored.
+        .register 8-)
 
         ! SPARC32: .byte 24
         ! SPARC64: .byte 24

diff  --git a/llvm/test/MC/SystemZ/gnu-attributes-invalid.s b/llvm/test/MC/SystemZ/gnu-attributes-invalid.s
new file mode 100644
index 00000000000000..c3080532db6c3f
--- /dev/null
+++ b/llvm/test/MC/SystemZ/gnu-attributes-invalid.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple s390x %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:1: error: malformed .gnu_attribute directive
+.gnu_attribute tag, value
+
+# CHECK: [[#@LINE+1]]:1: error: unrecognized .gnu_attribute tag/value pair.
+.gnu_attribute 42, 8
+
+# CHECK: [[#@LINE+1]]:1: error: unrecognized .gnu_attribute tag/value pair.
+.gnu_attribute 8, 42
+
+# CHECK: [[#@LINE+1]]:20: error: expected newline
+.gnu_attribute 8, 1$

diff  --git a/llvm/test/MC/SystemZ/machine-directive-invalid.s b/llvm/test/MC/SystemZ/machine-directive-invalid.s
new file mode 100644
index 00000000000000..8b3147ecc62d43
--- /dev/null
+++ b/llvm/test/MC/SystemZ/machine-directive-invalid.s
@@ -0,0 +1,10 @@
+# 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]]:10: error: unexpected token in '.machine' directive
+.machine 42
+
+# CHECK: [[#@LINE+1]]:13: error: expected newline
+.machine z13+

diff  --git a/llvm/test/MC/VE/data-size-error.s b/llvm/test/MC/VE/data-size-error.s
index 03139444d67649..c6188e03631329 100644
--- a/llvm/test/MC/VE/data-size-error.s
+++ b/llvm/test/MC/VE/data-size-error.s
@@ -34,3 +34,12 @@ a:
 # CHECK-NEXT: .quad 0xff5588aadeadbeafde
 # CHECK:      data-size-error.s:15:8: error: literal value out of range for directive
 # CHECK-NEXT: .llong 0xff5588aadeadbeafde
+
+# CHECK: [[#@LINE+1]]:17: error: unknown token in expression
+.word 0xd0bb1e +
+
+# CHECK: [[#@LINE+1]]:16: error: unexpected token
+.long 0xd0bb1e =
+
+# CHECK: [[#@LINE+1]]:10: error: unexpected token
+.llong 2 0xd0bb1e

diff  --git a/llvm/test/MC/WebAssembly/export-name-invalid.s b/llvm/test/MC/WebAssembly/export-name-invalid.s
new file mode 100644
index 00000000000000..ad322ce949f5ec
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/export-name-invalid.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:14: error: Expected identifier, got: 42
+.export_name 42
+
+# CHECK: [[#@LINE+1]]:17: error: Expected ,, instead got:
+.export_name foo
+
+# CHECK: [[#@LINE+1]]:18: error: Expected identifier, got:
+.export_name foo,
+
+# CHECK: [[#@LINE+1]]:22: error: Expected EOL, instead got: ,
+.export_name foo, bar,

diff  --git a/llvm/test/MC/WebAssembly/functype-invalid.s b/llvm/test/MC/WebAssembly/functype-invalid.s
new file mode 100644
index 00000000000000..89b90c56e76522
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/functype-invalid.s
@@ -0,0 +1,28 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:10: error: Expected identifier, got:
+.functype
+
+# CHECK: [[#@LINE+1]]:13: error: Expected (, instead got:
+.functype fn
+
+# CHECK: [[#@LINE+1]]:15: error: Expected ), instead got:
+.functype fn (
+
+# CHECK: [[#@LINE+1]]:15: error: unknown type: i42
+.functype fn (i42
+
+# CHECK: [[#@LINE+1]]:19: error: Expected ), instead got: i32
+.functype fn (i32 i32
+
+# CHECK: [[#@LINE+1]]:16: error: Expected ->, instead got:
+.functype fn ()
+
+# CHECK: [[#@LINE+1]]:17: error: Expected ->, instead got: <
+.functype fn () <- ()
+
+# CHECK: [[#@LINE+1]]:21: error: Expected ), instead got:
+.functype fn () -> (
+
+# CHECK: [[#@LINE+1]]:23: error: Expected EOL, instead got: ->
+.functype fn () -> () -> ()

diff  --git a/llvm/test/MC/WebAssembly/globaltype-invalid.s b/llvm/test/MC/WebAssembly/globaltype-invalid.s
new file mode 100644
index 00000000000000..26344e84a4c2c6
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/globaltype-invalid.s
@@ -0,0 +1,31 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:12: error: Expected identifier, got:
+.globaltype
+
+# CHECK: [[#@LINE+1]]:13: error: Expected identifier, got: 42
+.globaltype 42
+
+# CHECK: [[#@LINE+1]]:16: error: Expected ,, instead got:
+.globaltype sym
+
+# CHECK: [[#@LINE+1]]:17: error: Expected identifier, got:
+.globaltype sym,
+
+# CHECK: [[#@LINE+1]]:18: error: Expected identifier, got: 42
+.globaltype sym, 42
+
+# CHECK: [[#@LINE+1]]:18: error: Unknown type in .globaltype directive: i42
+.globaltype sym, i42
+
+# CHECK: [[#@LINE+1]]:22: error: Expected identifier, got:
+.globaltype sym, i32,
+
+# CHECK: [[#@LINE+1]]:23: error: Expected identifier, got: 42
+.globaltype sym, i32, 42
+
+# CHECK: [[#@LINE+1]]:23: error: Unknown type in .globaltype modifier: unmutable
+.globaltype sym, i32, unmutable
+
+# CHECK: [[#@LINE+1]]:32: error: Expected EOL, instead got: ,
+.globaltype sym, i32, immutable,

diff  --git a/llvm/test/MC/WebAssembly/import-module-invalid.s b/llvm/test/MC/WebAssembly/import-module-invalid.s
new file mode 100644
index 00000000000000..a9f93e83dba390
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/import-module-invalid.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:16: error: Expected identifier, got: 42
+.import_module 42
+
+# CHECK: [[#@LINE+1]]:19: error: Expected ,, instead got:
+.import_module foo
+
+# CHECK: [[#@LINE+1]]:20: error: Expected identifier, got:
+.import_module foo,
+
+# CHECK: [[#@LINE+1]]:24: error: Expected EOL, instead got: ,
+.import_module foo, bar,

diff  --git a/llvm/test/MC/WebAssembly/import-name-invalid.s b/llvm/test/MC/WebAssembly/import-name-invalid.s
new file mode 100644
index 00000000000000..da8ed0d4617b04
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/import-name-invalid.s
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:14: error: Expected identifier, got: 42
+.import_name 42
+
+# CHECK: [[#@LINE+1]]:17: error: Expected ,, instead got:
+.import_name foo
+
+# CHECK: [[#@LINE+1]]:18: error: Expected identifier, got:
+.import_name foo,
+
+# CHECK: [[#@LINE+1]]:22: error: Expected EOL, instead got: ,
+.import_name foo, bar,

diff  --git a/llvm/test/MC/WebAssembly/tabletype-invalid.s b/llvm/test/MC/WebAssembly/tabletype-invalid.s
new file mode 100644
index 00000000000000..4e50d057ad98bd
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/tabletype-invalid.s
@@ -0,0 +1,28 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:11: error: Expected identifier, got:
+.tabletype
+
+# CHECK: [[#@LINE+1]]:12: error: Expected identifier, got: 42
+.tabletype 42
+
+# CHECK: [[#@LINE+1]]:15: error: Expected ,, instead got:
+.tabletype sym
+
+# CHECK: [[#@LINE+1]]:16: error: Expected identifier, got:
+.tabletype sym,
+
+# CHECK: [[#@LINE+1]]:17: error: Expected identifier, got: 42
+.tabletype sym, 42
+
+# CHECK: [[#@LINE+1]]:17: error: Unknown type in .tabletype directive: i42
+.tabletype sym, i42
+
+# CHECK: [[#@LINE+1]]:21: error: Expected integer constant, instead got:
+.tabletype sym, i32,
+
+# CHECK: [[#@LINE+1]]:25: error: Expected integer constant, instead got:
+.tabletype sym, i32, 42,
+
+# CHECK: [[#@LINE+1]]:28: error: Expected EOL, instead got: ,
+.tabletype sym, i32, 42, 42,

diff  --git a/llvm/test/MC/WebAssembly/tagtype-invalid.s b/llvm/test/MC/WebAssembly/tagtype-invalid.s
new file mode 100644
index 00000000000000..6b562a4c18895e
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/tagtype-invalid.s
@@ -0,0 +1,10 @@
+# RUN: not llvm-mc -triple=wasm32 %s 2>&1 | FileCheck %s
+
+# CHECK: [[#@LINE+1]]:10: error: Expected identifier, got: 42
+.tagtype 42
+
+# CHECK: [[#@LINE+1]]:13: error: Expected EOL, instead got: ,
+.tagtype foo, i32
+
+# CHECK: [[#@LINE+1]]:18: error: Expected EOL, instead got: pub
+.tagtype bar i32 pub


        


More information about the llvm-commits mailing list