[llvm] Add diagnostic help for inline asm operand constraint 'H' (PR #88248)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 02:31:40 PDT 2024


https://github.com/mahesh-attarde created https://github.com/llvm/llvm-project/pull/88248

Using inline asm operand constraint 'H' with constants does not reflect helpful error.
With addition of this message operands those are not offsetable, will report exact root cause.
Originally https://reviews.llvm.org/D35890

>From 4459b041e386d68e5ffce8ccd738ad43da32ff79 Mon Sep 17 00:00:00 2001
From: mahesh-attarde <mahesh.attarde at intel.com>
Date: Sun, 7 Apr 2024 23:05:19 -0700
Subject: [PATCH 1/2] add diagnostic error code for inline asm operands
 constraints

---
 llvm/include/llvm/CodeGen/AsmPrinter.h        | 12 +++-
 llvm/include/llvm/IR/InlineAsm.h              | 16 ++++-
 .../AsmPrinter/AsmPrinterInlineAsm.cpp        | 54 +++++++++-------
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 48 +++++++++------
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp   | 21 ++++---
 llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h     |  5 +-
 llvm/lib/Target/ARM/ARMAsmPrinter.cpp         | 61 ++++++++++---------
 llvm/lib/Target/ARM/ARMAsmPrinter.h           |  5 +-
 llvm/lib/Target/AVR/AVRAsmPrinter.cpp         | 26 ++++----
 llvm/lib/Target/BPF/BPFAsmPrinter.cpp         | 13 ++--
 llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp       | 11 ++--
 llvm/lib/Target/CSKY/CSKYAsmPrinter.h         |  5 +-
 llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp | 17 +++---
 llvm/lib/Target/Hexagon/HexagonAsmPrinter.h   |  5 +-
 llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp     | 27 ++++----
 .../Target/LoongArch/LoongArchAsmPrinter.cpp  | 30 ++++-----
 .../Target/LoongArch/LoongArchAsmPrinter.h    |  5 +-
 llvm/lib/Target/M68k/M68kAsmPrinter.cpp       |  8 ++-
 llvm/lib/Target/M68k/M68kAsmPrinter.h         |  5 +-
 llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp   | 13 ++--
 llvm/lib/Target/Mips/MipsAsmPrinter.cpp       | 49 ++++++++-------
 llvm/lib/Target/Mips/MipsAsmPrinter.h         |  5 +-
 llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp     | 10 +--
 llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h       |  5 +-
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     | 24 +++++---
 llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp     | 34 ++++++-----
 llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp     | 17 ++++--
 llvm/lib/Target/Sparc/SparcAsmPrinter.cpp     | 17 +++---
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp |  9 +--
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.h   |  5 +-
 llvm/lib/Target/VE/VEAsmPrinter.cpp           | 15 +++--
 .../WebAssembly/WebAssemblyAsmPrinter.cpp     | 24 ++++----
 .../WebAssembly/WebAssemblyAsmPrinter.h       |  5 +-
 llvm/lib/Target/X86/X86AsmPrinter.cpp         | 61 +++++++++++++------
 llvm/lib/Target/X86/X86AsmPrinter.h           |  9 ++-
 llvm/lib/Target/XCore/XCoreAsmPrinter.cpp     | 13 ++--
 36 files changed, 413 insertions(+), 276 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 81c3e4be95e9ff..3c29b0133c5fcf 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -817,9 +817,15 @@ class AsmPrinter : public MachineFunctionPass {
   /// Print the specified operand of MI, an INLINEASM instruction, using the
   /// specified assembler variant.  Targets should override this to format as
   /// appropriate.  This method can return true if the operand is erroneous.
-  virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                               const char *ExtraCode, raw_ostream &OS);
-
+  virtual AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI,
+                                              unsigned OpNo,
+                                              const char *ExtraCode,
+                                              raw_ostream &OS);
+
+  /// Print Operand Constraint Error related helpful message
+  virtual void diagnoseAsmOperandError(LLVMContext &C,
+                                       const AsmOperandErrorCode,
+                                       const char *AsmStr, uint64_t Loc);
   /// Print the specified operand of MI, an INLINEASM instruction, using the
   /// specified assembler variant as an address. Targets should override this to
   /// format as appropriate.  This method can return true if the operand is
diff --git a/llvm/include/llvm/IR/InlineAsm.h b/llvm/include/llvm/IR/InlineAsm.h
index e5f506e5694daf..989bbe47006219 100644
--- a/llvm/include/llvm/IR/InlineAsm.h
+++ b/llvm/include/llvm/IR/InlineAsm.h
@@ -528,6 +528,20 @@ class InlineAsm final : public Value {
   }
 };
 
+/// Inline Asm specifies input & output constraint which can
+/// specifiy target specific criteria for operand. If this criteria
+/// does not match, we must throw error.
+/// NO_ERROR represents Operand constraints are valid/applicable
+/// OPERAND_ERROR represents some constraint(unspecified) failed
+/// UNKNOWN_MODIFIER_ERROR represents use of unknown char constraint
+/// CONSTRAINT_<char>_ERROR represents error regarding constraint.
+enum class AsmOperandErrorCode {
+  NO_ERROR = 0,
+  OPERAND_ERROR,
+  UNKNOWN_MODIFIER_ERROR,
+  CONSTRAINT_H_ERROR,
+};
+
 } // end namespace llvm
 
-#endif // LLVM_IR_INLINEASM_H
+#endif // LLVM_IR_INLINEASM_H
\ No newline at end of file
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index d0ef3e5a19391c..2aa7347ffc3ff6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -273,7 +273,7 @@ static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
         unsigned OpNo = InlineAsm::MIOp_FirstOperand;
 
         bool Error = false;
-
+        AsmOperandErrorCode OpErrorCode = AsmOperandErrorCode::NO_ERROR;
         // Scan to find the machine operand number for the operand.
         for (; Val; --Val) {
           if (OpNo >= MI->getNumOperands())
@@ -306,15 +306,15 @@ static void EmitInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
             Error = AP->PrintAsmMemoryOperand(
                 MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
           } else {
-            Error = AP->PrintAsmOperand(MI, OpNo,
-                                        Modifier[0] ? Modifier : nullptr, OS);
+            OpErrorCode = AP->PrintAsmOperand(
+                MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
           }
         }
-        if (Error) {
-          std::string msg;
-          raw_string_ostream Msg(msg);
-          Msg << "invalid operand in inline asm: '" << AsmStr << "'";
-          MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
+        if (Error || (OpErrorCode != AsmOperandErrorCode::NO_ERROR)) {
+          if (Error)
+            OpErrorCode = AsmOperandErrorCode::OPERAND_ERROR;
+          AP->diagnoseAsmOperandError(MMI->getModule()->getContext(),
+                                      OpErrorCode, AsmStr, LocCookie);
         }
       }
       break;
@@ -461,50 +461,62 @@ void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) {
   printOffset(MO.getOffset(), OS);
 }
 
+void AsmPrinter::diagnoseAsmOperandError(LLVMContext &C,
+                                         const AsmOperandErrorCode ErrCode,
+                                         const char *AsmStr,
+                                         const uint64_t Loc) {
+  std::string msg;
+  raw_string_ostream Msg(msg);
+  Msg << "invalid operand in inline asm: '" << AsmStr << "'";
+  C.emitError(Loc, Msg.str());
+}
 /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
 /// instruction, using the specified assembler variant.  Targets should
 /// override this to format as appropriate for machine specific ExtraCodes
 /// or when the arch-independent handling would be too complex otherwise.
-bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                 const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode AsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                unsigned OpNo,
+                                                const char *ExtraCode,
+                                                raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     // https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html
     const MachineOperand &MO = MI->getOperand(OpNo);
     switch (ExtraCode[0]) {
     default:
-      return true;  // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
     case 'a': // Print as memory address.
       if (MO.isReg()) {
         PrintAsmMemoryOperand(MI, OpNo, nullptr, O);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       [[fallthrough]]; // GCC allows '%a' to behave like '%c' with immediates.
     case 'c': // Substitute immediate value without immediate syntax
       if (MO.isImm()) {
         O << MO.getImm();
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       if (MO.isGlobal()) {
         PrintSymbolOperand(MO, O);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     case 'n':  // Negate the immediate constant.
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << -MO.getImm();
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 's':  // The GCC deprecated s modifier
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << ((32 - MO.getImm()) & 31);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
   }
-  return true;
+  return AsmOperandErrorCode::OPERAND_ERROR;
 }
 
 bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index f6ccd0ecfdc893..cdc54ca545be88 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -176,8 +176,9 @@ class AArch64AsmPrinter : public AsmPrinter {
                           const TargetRegisterClass *RC, unsigned AltName,
                           raw_ostream &O);
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                              const char *ExtraCode, raw_ostream &O) override;
 
@@ -915,33 +916,38 @@ bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
   return false;
 }
 
-bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                                        const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                       unsigned OpNum,
+                                                       const char *ExtraCode,
+                                                       raw_ostream &O) {
   const MachineOperand &MO = MI->getOperand(OpNum);
 
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
     case 'w':      // Print W register
     case 'x':      // Print X register
       if (MO.isReg())
-        return printAsmMRegister(MO, ExtraCode[0], O);
+        return (printAsmMRegister(MO, ExtraCode[0], O)
+                    ? AsmOperandErrorCode::OPERAND_ERROR
+                    : AsmOperandErrorCode::NO_ERROR);
       if (MO.isImm() && MO.getImm() == 0) {
         unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
         O << AArch64InstPrinter::getRegisterName(Reg);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       printOperand(MI, OpNum, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'b': // Print B register.
     case 'h': // Print H register.
     case 's': // Print S register.
@@ -970,12 +976,14 @@ bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
           RC = &AArch64::ZPRRegClass;
           break;
         default:
-          return true;
+          return AsmOperandErrorCode::OPERAND_ERROR;
         }
-        return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
+        return (printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O)
+                    ? AsmOperandErrorCode::OPERAND_ERROR
+                    : AsmOperandErrorCode::NO_ERROR);
       }
       printOperand(MI, OpNum, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
   }
 
@@ -987,11 +995,13 @@ bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     // If this is a w or x register, print an x register.
     if (AArch64::GPR32allRegClass.contains(Reg) ||
         AArch64::GPR64allRegClass.contains(Reg))
-      return printAsmMRegister(MO, 'x', O);
+      return (printAsmMRegister(MO, 'x', O) ? AsmOperandErrorCode::OPERAND_ERROR
+                                            : AsmOperandErrorCode::NO_ERROR);
 
     // If this is an x register tuple, print an x register.
     if (AArch64::GPR64x8ClassRegClass.contains(Reg))
-      return printAsmMRegister(MO, 't', O);
+      return (printAsmMRegister(MO, 't', O) ? AsmOperandErrorCode::OPERAND_ERROR
+                                            : AsmOperandErrorCode::NO_ERROR);
 
     unsigned AltName = AArch64::NoRegAltName;
     const TargetRegisterClass *RegClass;
@@ -1007,11 +1017,13 @@ bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     }
 
     // If this is a b, h, s, d, or q register, print it as a v register.
-    return printAsmRegInClass(MO, RegClass, AltName, O);
+    return (printAsmRegInClass(MO, RegClass, AltName, O)
+                ? AsmOperandErrorCode::OPERAND_ERROR
+                : AsmOperandErrorCode::NO_ERROR);
   }
 
   printOperand(MI, OpNum, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index 052b231d62a3eb..5b60a210d08588 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -1240,21 +1240,24 @@ void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out,
   Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
 }
 
-bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                       const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                      unsigned OpNo,
+                                                      const char *ExtraCode,
+                                                      raw_ostream &O) {
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     case 'r':
       break;
     default:
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     }
   }
 
@@ -1263,7 +1266,7 @@ bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   if (MO.isReg()) {
     AMDGPUInstPrinter::printRegOperand(MO.getReg(), O,
                                        *MF->getSubtarget().getRegisterInfo());
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   } else if (MO.isImm()) {
     int64_t Val = MO.getImm();
     if (AMDGPU::isInlinableIntLiteral(Val)) {
@@ -1275,9 +1278,9 @@ bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     } else {
       O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
     }
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   }
-  return true;
+  return AsmOperandErrorCode::OPERAND_ERROR;
 }
 
 void AMDGPUAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
index b8b2718d293e69..5a3032ba6075ff 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h
@@ -125,8 +125,9 @@ class AMDGPUAsmPrinter final : public AsmPrinter {
 
   void emitEndOfAsmFile(Module &M) override;
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
 
 protected:
   void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index 642739a29d6b06..9fa0c2b7ecff7c 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -283,11 +283,14 @@ GetARMJTIPICJumpTableLabel(unsigned uid) const {
   return OutContext.getOrCreateSymbol(Name);
 }
 
-bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                                    const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                   unsigned OpNum,
+                                                   const char *ExtraCode,
+                                                   raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -296,7 +299,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     case 'P': // Print a VFP double precision register.
     case 'q': // Print a NEON quad precision register.
       printOperand(MI, OpNum, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'y': // Print a VFP single precision register as indexed double.
       if (MI->getOperand(OpNum).isReg()) {
         MCRegister Reg = MI->getOperand(OpNum).getReg().asMCReg();
@@ -308,23 +311,23 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
             continue;
           bool Lane0 = TRI->getSubReg(SR, ARM::ssub_0) == Reg;
           O << ARMInstPrinter::getRegisterName(SR) << (Lane0 ? "[0]" : "[1]");
-          return false;
+          return AsmOperandErrorCode::NO_ERROR;
         }
       }
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     case 'B': // Bitwise inverse of integer or symbol without a preceding #.
       if (!MI->getOperand(OpNum).isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << ~(MI->getOperand(OpNum).getImm());
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'L': // The low 16 bits of an immediate constant.
       if (!MI->getOperand(OpNum).isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << (MI->getOperand(OpNum).getImm() & 0xffff);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'M': { // A register range suitable for LDM/STM.
       if (!MI->getOperand(OpNum).isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &MO = MI->getOperand(OpNum);
       Register RegBegin = MO.getReg();
       // This takes advantage of the 2 operand-ness of ldm/stm and that we've
@@ -352,15 +355,15 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
 
       O << "}";
 
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
     case 'R': // The most significant register of a pair.
     case 'Q': { // The least significant register of a pair.
       if (OpNum == 0)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
       if (!FlagsOP.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       InlineAsm::Flag F(FlagsOP.getImm());
 
       // This operand may not be the one that actually provides the register. If
@@ -398,64 +401,64 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
       if (F.hasRegClassConstraint(RC) &&
           ARM::GPRPairRegClass.hasSubClassEq(TRI->getRegClass(RC))) {
         if (NumVals != 1)
-          return true;
+          return AsmOperandErrorCode::OPERAND_ERROR;
         const MachineOperand &MO = MI->getOperand(OpNum);
         if (!MO.isReg())
-          return true;
+          return AsmOperandErrorCode::OPERAND_ERROR;
         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
         Register Reg =
             TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1);
         O << ARMInstPrinter::getRegisterName(Reg);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       if (NumVals != 2)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       unsigned RegOp = FirstHalf ? OpNum : OpNum + 1;
       if (RegOp >= MI->getNumOperands())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &MO = MI->getOperand(RegOp);
       if (!MO.isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       Register Reg = MO.getReg();
       O << ARMInstPrinter::getRegisterName(Reg);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
 
     case 'e': // The low doubleword register of a NEON quad register.
     case 'f': { // The high doubleword register of a NEON quad register.
       if (!MI->getOperand(OpNum).isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       Register Reg = MI->getOperand(OpNum).getReg();
       if (!ARM::QPRRegClass.contains(Reg))
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
       Register SubReg =
           TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);
       O << ARMInstPrinter::getRegisterName(SubReg);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
 
     // This modifier is not yet supported.
     case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     case 'H': { // The highest-numbered register of a pair.
       const MachineOperand &MO = MI->getOperand(OpNum);
       if (!MO.isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineFunction &MF = *MI->getParent()->getParent();
       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
       Register Reg = MO.getReg();
       if(!ARM::GPRPairRegClass.contains(Reg))
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       Reg = TRI->getSubReg(Reg, ARM::gsub_1);
       O << ARMInstPrinter::getRegisterName(Reg);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
     }
   }
 
   printOperand(MI, OpNum, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h
index 33b4417aa9b809..0c66ed16340dfa 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.h
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h
@@ -76,8 +76,9 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter {
   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
 
   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                              const char *ExtraCode, raw_ostream &O) override;
 
diff --git a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
index 1c8213b668f71a..003171a49cde87 100644
--- a/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
+++ b/llvm/lib/Target/AVR/AVRAsmPrinter.cpp
@@ -51,8 +51,9 @@ class AVRAsmPrinter : public AsmPrinter {
 
   void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
 
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                              const char *ExtraCode, raw_ostream &O) override;
@@ -97,23 +98,26 @@ void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
   }
 }
 
-bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                                    const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                   unsigned OpNum,
+                                                   const char *ExtraCode,
+                                                   raw_ostream &O) {
   // Default asm printer can only deal with some extra codes,
   // so try it first.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   const MachineOperand &MO = MI->getOperand(OpNum);
 
   if (ExtraCode && ExtraCode[0]) {
     // Unknown extra code.
     if (ExtraCode[1] != 0 || ExtraCode[0] < 'A' || ExtraCode[0] > 'Z')
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
 
     // Operand must be a register when using 'A' ~ 'Z' extra code.
     if (!MO.isReg())
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
 
     Register Reg = MO.getReg();
 
@@ -130,7 +134,7 @@ bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
 
     unsigned RegIdx = ByteNumber / BytesPerReg;
     if (RegIdx >= NumOpRegs)
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     Reg = MI->getOperand(OpNum + RegIdx).getReg();
 
     if (BytesPerReg == 2) {
@@ -139,7 +143,7 @@ bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     }
 
     O << AVRInstPrinter::getPrettyRegisterName(Reg, MRI);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   }
 
   if (MO.getType() == MachineOperand::MO_GlobalAddress)
@@ -147,7 +151,7 @@ bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
   else
     printOperand(MI, OpNum, O); // Fallback to ordinary cases.
 
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool AVRAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
index c8849bd50464c7..289efe677b2559 100644
--- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -43,8 +43,9 @@ class BPFAsmPrinter : public AsmPrinter {
   StringRef getPassName() const override { return "BPF Assembly Printer"; }
   bool doInitialization(Module &M) override;
   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                              const char *ExtraCode, raw_ostream &O) override;
 
@@ -107,13 +108,15 @@ void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
   }
 }
 
-bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                    const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                   unsigned OpNo,
+                                                   const char *ExtraCode,
+                                                   raw_ostream &O) {
   if (ExtraCode && ExtraCode[0])
     return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
 
   printOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
index 7d121b8d24f059..39d4d5bcd49eca 100644
--- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
+++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.cpp
@@ -260,11 +260,14 @@ void CSKYAsmPrinter::emitAttributes() {
   CTS.emitTargetAttributes(STI);
 }
 
-bool CSKYAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                     const char *ExtraCode, raw_ostream &OS) {
+AsmOperandErrorCode CSKYAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                    unsigned OpNo,
+                                                    const char *ExtraCode,
+                                                    raw_ostream &OS) {
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   const MachineOperand &MO = MI->getOperand(OpNo);
   if (ExtraCode && ExtraCode[0]) {
diff --git a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
index 379189512405ab..497043b4812605 100644
--- a/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
+++ b/llvm/lib/Target/CSKY/CSKYAsmPrinter.h
@@ -59,8 +59,9 @@ class LLVM_LIBRARY_VISIBILITY CSKYAsmPrinter : public AsmPrinter {
   // we emit constant pools customly!
   void emitConstantPool() override {}
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
 
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
index d2f64ac9e90b0b..d27c0c9b4ae772 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp
@@ -112,13 +112,14 @@ bool HexagonAsmPrinter::isBlockOnlyReachableByFallthrough(
 }
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
-bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                        const char *ExtraCode,
-                                        raw_ostream &OS) {
+AsmOperandErrorCode HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                       unsigned OpNo,
+                                                       const char *ExtraCode,
+                                                       raw_ostream &OS) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -130,7 +131,7 @@ bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
       const MachineFunction &MF = *MI->getParent()->getParent();
       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
       if (!MO.isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       Register RegNumber = MO.getReg();
       // This should be an assert in the frontend.
       if (Hexagon::DoubleRegsRegClass.contains(RegNumber))
@@ -138,19 +139,19 @@ bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                               Hexagon::isub_lo :
                                               Hexagon::isub_hi);
       OS << HexagonInstPrinter::getRegisterName(RegNumber);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
     case 'I':
       // Write 'i' if an integer constant, otherwise nothing.  Used to print
       // addi vs add, etc.
       if (MI->getOperand(OpNo).isImm())
         OS << "i";
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
   }
 
   printOperand(MI, OpNo, OS);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
index b555c885965036..274ec7bd3f4eac 100644
--- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
+++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h
@@ -66,8 +66,9 @@ class TargetMachine;
     void HexagonProcessInstruction(MCInst &Inst, const MachineInstr &MBB);
 
     void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
-    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                         const char *ExtraCode, raw_ostream &OS) override;
+    AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                        const char *ExtraCode,
+                                        raw_ostream &OS) override;
     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                                const char *ExtraCode, raw_ostream &OS) override;
     void emitStartOfAsmFile(Module &M) override;
diff --git a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
index c66d9166828c10..ad7b0d518ad6d0 100644
--- a/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
+++ b/llvm/lib/Target/Lanai/LanaiAsmPrinter.cpp
@@ -49,8 +49,9 @@ class LanaiAsmPrinter : public AsmPrinter {
   StringRef getPassName() const override { return "Lanai Assembly Printer"; }
 
   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   void emitInstruction(const MachineInstr *MI) override;
   bool isBlockOnlyReachableByFallthrough(
       const MachineBasicBlock *MBB) const override;
@@ -108,41 +109,43 @@ void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
 }
 
 // PrintAsmOperand - Print out an operand for an inline asm expression.
-bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1])
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     // The highest-numbered register of a pair.
     case 'H': {
       if (OpNo == 0)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
       if (!FlagsOP.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const InlineAsm::Flag Flags(FlagsOP.getImm());
       const unsigned NumVals = Flags.getNumOperandRegisters();
       if (NumVals != 2)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       unsigned RegOp = OpNo + 1;
       if (RegOp >= MI->getNumOperands())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &MO = MI->getOperand(RegOp);
       if (!MO.isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       Register Reg = MO.getReg();
       O << LanaiInstPrinter::getRegisterName(Reg);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
     default:
       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
     }
   }
   printOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index 27979a830b10e6..869ae6896a11fa 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -54,25 +54,27 @@ void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
     EmitToStreamer(*OutStreamer, TmpInst);
 }
 
-bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                          const char *ExtraCode,
-                                          raw_ostream &OS) {
+AsmOperandErrorCode LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                         unsigned OpNo,
+                                                         const char *ExtraCode,
+                                                         raw_ostream &OS) {
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   const MachineOperand &MO = MI->getOperand(OpNo);
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
     case 'z':      // Print $zero register if zero, regular printing otherwise.
       if (MO.isImm() && MO.getImm() == 0) {
         OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       break;
     case 'w': // Print LSX registers.
@@ -81,14 +83,14 @@ bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
         break;
       // The modifier is 'w' but the operand is not an LSX register; Report an
       // unknown operand error.
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
     case 'u': // Print LASX registers.
       if (MO.getReg().id() >= LoongArch::XR0 &&
           MO.getReg().id() <= LoongArch::XR31)
         break;
       // The modifier is 'u' but the operand is not an LASX register; Report an
       // unknown operand error.
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
       // TODO: handle other extra codes if any.
     }
   }
@@ -96,18 +98,18 @@ bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   switch (MO.getType()) {
   case MachineOperand::MO_Immediate:
     OS << MO.getImm();
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   case MachineOperand::MO_Register:
     OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   case MachineOperand::MO_GlobalAddress:
     PrintSymbolOperand(MO, OS);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   default:
     llvm_unreachable("not implemented");
   }
 
-  return true;
+  return AsmOperandErrorCode::OPERAND_ERROR;
 }
 
 bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
index 693456443c7a48..aca6d07baa9f25 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -36,8 +36,9 @@ class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter {
 
   void emitInstruction(const MachineInstr *MI) override;
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
 
diff --git a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
index f748450c170aa6..59fcebb9604f9c 100644
--- a/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
+++ b/llvm/lib/Target/M68k/M68kAsmPrinter.cpp
@@ -64,12 +64,14 @@ void M68kAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
   }
 }
 
-bool M68kAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                     const char *ExtraCode, raw_ostream &OS) {
+AsmOperandErrorCode M68kAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                    unsigned OpNo,
+                                                    const char *ExtraCode,
+                                                    raw_ostream &OS) {
   // Print the operand if there is no operand modifier.
   if (!ExtraCode || !ExtraCode[0]) {
     printOperand(MI, OpNo, OS);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   }
 
   // Fallback to the default implementation.
diff --git a/llvm/lib/Target/M68k/M68kAsmPrinter.h b/llvm/lib/Target/M68k/M68kAsmPrinter.h
index 7b4dbfef58c57e..2951b8c2971741 100644
--- a/llvm/lib/Target/M68k/M68kAsmPrinter.h
+++ b/llvm/lib/Target/M68k/M68kAsmPrinter.h
@@ -63,8 +63,9 @@ class LLVM_LIBRARY_VISIBILITY M68kAsmPrinter
 
   virtual bool runOnMachineFunction(MachineFunction &MF) override;
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
 
diff --git a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
index 9cd2cbe89e461f..eb525117db9197 100644
--- a/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
+++ b/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
@@ -53,8 +53,9 @@ namespace {
                       raw_ostream &O, const char* Modifier = nullptr);
     void printSrcMemOperand(const MachineInstr *MI, int OpNum,
                             raw_ostream &O);
-    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                         const char *ExtraCode, raw_ostream &O) override;
+    AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                        const char *ExtraCode,
+                                        raw_ostream &O) override;
     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                                const char *ExtraCode, raw_ostream &O) override;
     void emitInstruction(const MachineInstr *MI) override;
@@ -126,14 +127,16 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                       const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                      unsigned OpNo,
+                                                      const char *ExtraCode,
+                                                      raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0])
     return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
 
   printOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
index 66b2b0de8d52a3..4c131ed2ae9abf 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -472,11 +472,14 @@ void MipsAsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
 }
 
 // Print out an operand for an inline asm expression.
-bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
-                                     const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                    unsigned OpNum,
+                                                    const char *ExtraCode,
+                                                    raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     const MachineOperand &MO = MI->getOperand(OpNum);
     switch (ExtraCode[0]) {
@@ -485,36 +488,36 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
       return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);
     case 'X': // hex const int
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << "0x" << Twine::utohexstr(MO.getImm());
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'x': // hex const int (low 16 bits)
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'd': // decimal const int
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << MO.getImm();
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'm': // decimal const int minus 1
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << MO.getImm() - 1;
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'y': // exact log2
       if (!MO.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       if (!isPowerOf2_64(MO.getImm()))
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       O << Log2_64(MO.getImm());
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'z':
       // $0 if zero, regular printing otherwise
       if (MO.isImm() && MO.getImm() == 0) {
         O << "$0";
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       // If not, call printOperand as normal.
       break;
@@ -523,10 +526,10 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
     case 'M': // High order register of a double word register operand
     {
       if (OpNum == 0)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
       if (!FlagsOP.isImm())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       const InlineAsm::Flag Flags(FlagsOP.getImm());
       const unsigned NumVals = Flags.getNumOperandRegisters();
       // Number of registers represented by this operand. We are looking
@@ -535,9 +538,9 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
         if (Subtarget->isGP64bit() && NumVals == 1 && MO.isReg()) {
           Register Reg = MO.getReg();
           O << '$' << MipsInstPrinter::getRegisterName(Reg);
-          return false;
+          return AsmOperandErrorCode::NO_ERROR;
         }
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       }
 
       unsigned RegOp = OpNum;
@@ -555,13 +558,13 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
           RegOp = OpNum + 1;
         }
         if (RegOp >= MI->getNumOperands())
-          return true;
+          return AsmOperandErrorCode::OPERAND_ERROR;
         const MachineOperand &MO = MI->getOperand(RegOp);
         if (!MO.isReg())
-          return true;
+          return AsmOperandErrorCode::OPERAND_ERROR;
         Register Reg = MO.getReg();
         O << '$' << MipsInstPrinter::getRegisterName(Reg);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       break;
     }
@@ -574,7 +577,7 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
   }
 
   printOperand(MI, OpNum, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.h b/llvm/lib/Target/Mips/MipsAsmPrinter.h
index 0b55089385d79d..f3804db1bb31dd 100644
--- a/llvm/lib/Target/Mips/MipsAsmPrinter.h
+++ b/llvm/lib/Target/Mips/MipsAsmPrinter.h
@@ -142,8 +142,9 @@ class LLVM_LIBRARY_VISIBILITY MipsAsmPrinter : public AsmPrinter {
   void emitFunctionBodyStart() override;
   void emitFunctionBodyEnd() override;
   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                              const char *ExtraCode, raw_ostream &O) override;
   void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index 9f31b72bbceb1f..96fecd2d200ced 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -2170,11 +2170,13 @@ void NVPTXAsmPrinter::printMCExpr(const MCExpr &Expr, raw_ostream &OS) {
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &O) {
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -2187,7 +2189,7 @@ bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 
   printOperand(MI, OpNo, O);
 
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool NVPTXAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
index 979d185a97f799..a469a5493c2697 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.h
@@ -183,8 +183,9 @@ class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter {
   void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
   void printReturnValStr(const Function *, raw_ostream &O);
   void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &) override;
   void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &) override;
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 16942c6893a16d..b4c837c30aaa06 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -196,8 +196,9 @@ class PPCAsmPrinter : public AsmPrinter {
   void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
 
   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &O) override;
 
@@ -355,11 +356,14 @@ void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                    const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                   unsigned OpNo,
+                                                   const char *ExtraCode,
+                                                   raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -370,7 +374,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
       if (!MI->getOperand(OpNo).isReg() ||
           OpNo+1 == MI->getNumOperands() ||
           !MI->getOperand(OpNo+1).isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       ++OpNo;   // Return the high-part.
       break;
     case 'I':
@@ -378,10 +382,10 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
       // addi vs add, etc.
       if (MI->getOperand(OpNo).isImm())
         O << "i";
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case 'x':
       if(!MI->getOperand(OpNo).isReg())
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       // This operand uses VSX numbering.
       // If the operand is a VMX register, convert it to a VSX register.
       Register Reg = MI->getOperand(OpNo).getReg();
@@ -393,12 +397,12 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
       RegName = PPCInstPrinter::getRegisterName(Reg);
       RegName = PPC::stripRegisterPrefix(RegName);
       O << RegName;
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
   }
 
   printOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 // At the moment, all inline asm memory operands are a single register.
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 9982a73ee914d9..e4e09269b296a8 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -75,8 +75,9 @@ class RISCVAsmPrinter : public AsmPrinter {
 
   void emitInstruction(const MachineInstr *MI) override;
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
 
@@ -262,53 +263,56 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
     EmitToStreamer(*OutStreamer, OutInst);
 }
 
-bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode, raw_ostream &OS) {
+AsmOperandErrorCode RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &OS) {
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   const MachineOperand &MO = MI->getOperand(OpNo);
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
     case 'z':      // Print zero register if zero, regular printing otherwise.
       if (MO.isImm() && MO.getImm() == 0) {
         OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       break;
     case 'i': // Literal 'i' if operand is not a register.
       if (!MO.isReg())
         OS << 'i';
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
   }
 
   switch (MO.getType()) {
   case MachineOperand::MO_Immediate:
     OS << MO.getImm();
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   case MachineOperand::MO_Register:
     OS << RISCVInstPrinter::getRegisterName(MO.getReg());
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   case MachineOperand::MO_GlobalAddress:
     PrintSymbolOperand(MO, OS);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   case MachineOperand::MO_BlockAddress: {
     MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
     Sym->print(OS, MAI);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   }
   default:
     break;
   }
 
-  return true;
+  return AsmOperandErrorCode::OPERAND_ERROR;
 }
 
 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index 1de4616fd5b774..f85c3b8180377e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -55,8 +55,9 @@ class SPIRVAsmPrinter : public AsmPrinter {
 
   StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
 
   void outputMCInst(MCInst &Inst);
   void outputInstruction(const MachineInstr *MI);
@@ -219,13 +220,17 @@ void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
   }
 }
 
-bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &O) {
   if (ExtraCode && ExtraCode[0])
-    return true; // Invalid instruction - SPIR-V does not have special modifiers
+    return AsmOperandErrorCode::OPERAND_ERROR; // Invalid instruction - SPIR-V
+                                               // does not have special
+                                               // modifiers
 
   printOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 static bool isFuncOrHeaderInstr(const MachineInstr *MI,
diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
index 6855471840e9db..ae20ab4e293a2b 100644
--- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -60,8 +60,9 @@ namespace {
       return SparcInstPrinter::getRegisterName(Reg);
     }
 
-    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                         const char *ExtraCode, raw_ostream &O) override;
+    AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                        const char *ExtraCode,
+                                        raw_ostream &O) override;
     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                                const char *ExtraCode, raw_ostream &O) override;
 
@@ -424,11 +425,13 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode,
-                                      raw_ostream &O) {
+AsmOperandErrorCode SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &O) {
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -486,7 +489,7 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 
   printOperand(MI, OpNo, O);
 
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 5696ae117d69f0..000d6bece4366d 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -925,9 +925,10 @@ static void printAddress(const MCAsmInfo *MAI, unsigned Base,
   }
 }
 
-bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                        const char *ExtraCode,
-                                        raw_ostream &OS) {
+AsmOperandErrorCode SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                       unsigned OpNo,
+                                                       const char *ExtraCode,
+                                                       raw_ostream &OS) {
   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
   const MachineOperand &MO = MI->getOperand(OpNo);
   MCOperand MCOp;
@@ -943,7 +944,7 @@ bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     MCOp = Lower.lowerOperand(MO);
   }
   printOperand(MCOp, MAI, OS);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index 303cce1a1b6581..b1ef3ff1f65acb 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -106,8 +106,9 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
   void emitInstruction(const MachineInstr *MI) override;
   void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
   void emitEndOfAsmFile(Module &M) override;
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
 
diff --git a/llvm/lib/Target/VE/VEAsmPrinter.cpp b/llvm/lib/Target/VE/VEAsmPrinter.cpp
index bdbc29f984b4c4..5d0ddab2ccb165 100644
--- a/llvm/lib/Target/VE/VEAsmPrinter.cpp
+++ b/llvm/lib/Target/VE/VEAsmPrinter.cpp
@@ -61,8 +61,9 @@ class VEAsmPrinter : public AsmPrinter {
     return VEInstPrinter::getRegisterName(Reg);
   }
   void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &OS);
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &O) override;
 };
@@ -373,11 +374,13 @@ void VEAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
 }
 
 // PrintAsmOperand - Print out an operand for an inline asm expression.
-bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                   const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                  unsigned OpNo,
+                                                  const char *ExtraCode,
+                                                  raw_ostream &O) {
   if (ExtraCode && ExtraCode[0]) {
     if (ExtraCode[1] != 0)
-      return true; // Unknown modifier.
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     switch (ExtraCode[0]) {
     default:
@@ -391,7 +394,7 @@ bool VEAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 
   printOperand(MI, OpNo, O);
 
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool VEAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 3524abba8990aa..fc515df4b295cd 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -688,42 +688,42 @@ void WebAssemblyAsmPrinter::emitInstruction(const MachineInstr *MI) {
   }
 }
 
-bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
-                                            unsigned OpNo,
-                                            const char *ExtraCode,
-                                            raw_ostream &OS) {
+AsmOperandErrorCode
+WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                       const char *ExtraCode, raw_ostream &OS) {
   // First try the generic code, which knows about modifiers like 'c' and 'n'.
-  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
-    return false;
+  if (AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS) ==
+      AsmOperandErrorCode::NO_ERROR)
+    return AsmOperandErrorCode::NO_ERROR;
 
   if (!ExtraCode) {
     const MachineOperand &MO = MI->getOperand(OpNo);
     switch (MO.getType()) {
     case MachineOperand::MO_Immediate:
       OS << MO.getImm();
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case MachineOperand::MO_Register:
       // FIXME: only opcode that still contains registers, as required by
       // MachineInstr::getDebugVariable().
       assert(MI->getOpcode() == WebAssembly::INLINEASM);
       OS << regToString(MO);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case MachineOperand::MO_GlobalAddress:
       PrintSymbolOperand(MO, OS);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case MachineOperand::MO_ExternalSymbol:
       GetExternalSymbolSymbol(MO.getSymbolName())->print(OS, MAI);
       printOffset(MO.getOffset(), OS);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     case MachineOperand::MO_MachineBasicBlock:
       MO.getMBB()->getSymbol()->print(OS, MAI);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     default:
       break;
     }
   }
 
-  return true;
+  return AsmOperandErrorCode::OPERAND_ERROR;
 }
 
 bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index 6a544abe6ce830..e71178b7450186 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -61,8 +61,9 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
   void emitConstantPool() override;
   void emitFunctionBodyStart() override;
   void emitInstruction(const MachineInstr *MI) override;
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &OS) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &OS) override;
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &OS) override;
 
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 3395a13545e454..a0a8f0938883ee 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -692,13 +692,32 @@ static bool printAsmVRegister(const MachineOperand &MO, char Mode,
   return false;
 }
 
+void X86AsmPrinter::diagnoseAsmOperandError(LLVMContext &C,
+                                            const AsmOperandErrorCode EC,
+                                            const char *AsmStr, uint64_t Loc) {
+  AsmPrinter::diagnoseAsmOperandError(C, EC, AsmStr, Loc);
+  std::string msg;
+  raw_string_ostream Msg(msg);
+  switch (EC) {
+  default:
+    break;
+  case AsmOperandErrorCode::CONSTRAINT_H_ERROR:
+    Msg << " 'H' modifier used on an operand that is a non-offsetable memory "
+           "reference.";
+    break;
+  }
+  C.emitError(Msg.str());
+}
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                    const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                   unsigned OpNo,
+                                                   const char *ExtraCode,
+                                                   raw_ostream &O) {
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
-    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    if (ExtraCode[1] != 0)
+      return AsmOperandErrorCode::UNKNOWN_MODIFIER_ERROR; // Unknown modifier.
 
     const MachineOperand &MO = MI->getOperand(OpNo);
 
@@ -709,10 +728,10 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     case 'a': // This is an address.  Currently only 'i' and 'r' are expected.
       switch (MO.getType()) {
       default:
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       case MachineOperand::MO_Immediate:
         O << MO.getImm();
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       case MachineOperand::MO_ConstantPoolIndex:
       case MachineOperand::MO_JumpTableIndex:
       case MachineOperand::MO_ExternalSymbol:
@@ -721,12 +740,12 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
         PrintSymbolOperand(MO, O);
         if (Subtarget->isPICStyleRIPRel())
           O << "(%rip)";
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       case MachineOperand::MO_Register:
         O << '(';
         PrintOperand(MI, OpNo, O);
         O << ')';
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
 
     case 'c': // Don't print "$" before a global var name or constant.
@@ -745,15 +764,15 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
         PrintSymbolOperand(MO, O);
         break;
       }
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
 
     case 'A': // Print '*' before a register (it must be a register)
       if (MO.isReg()) {
         O << '*';
         PrintOperand(MI, OpNo, O);
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
-      return true;
+      return AsmOperandErrorCode::OPERAND_ERROR;
 
     case 'b': // Print QImode register
     case 'h': // Print QImode high register
@@ -762,43 +781,47 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     case 'q': // Print DImode register
     case 'V': // Print native register without '%'
       if (MO.isReg())
-        return printAsmMRegister(*this, MO, ExtraCode[0], O);
+        return (printAsmMRegister(*this, MO, ExtraCode[0], O)
+                    ? AsmOperandErrorCode::OPERAND_ERROR
+                    : AsmOperandErrorCode::NO_ERROR);
       PrintOperand(MI, OpNo, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
 
     case 'x': // Print V4SFmode register
     case 't': // Print V8SFmode register
     case 'g': // Print V16SFmode register
       if (MO.isReg())
-        return printAsmVRegister(MO, ExtraCode[0], O);
+        return (printAsmVRegister(MO, ExtraCode[0], O)
+                    ? AsmOperandErrorCode::OPERAND_ERROR
+                    : AsmOperandErrorCode::NO_ERROR);
       PrintOperand(MI, OpNo, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
 
     case 'p': {
       const MachineOperand &MO = MI->getOperand(OpNo);
       if (MO.getType() != MachineOperand::MO_GlobalAddress)
-        return true;
+        return AsmOperandErrorCode::OPERAND_ERROR;
       PrintSymbolOperand(MO, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
 
     case 'P': // This is the operand of a call, treat specially.
       PrintPCRelImm(MI, OpNo, O);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
 
     case 'n': // Negate the immediate or print a '-' before the operand.
       // Note: this is a temporary solution. It should be handled target
       // independently as part of the 'MC' work.
       if (MO.isImm()) {
         O << -MO.getImm();
-        return false;
+        return AsmOperandErrorCode::NO_ERROR;
       }
       O << '-';
     }
   }
 
   PrintOperand(MI, OpNo, O);
-  return false;
+  return AsmOperandErrorCode::NO_ERROR;
 }
 
 bool X86AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h
index 693021eca32958..0b69a12950a288 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.h
+++ b/llvm/lib/Target/X86/X86AsmPrinter.h
@@ -143,8 +143,13 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
 
   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
 
-  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                       const char *ExtraCode, raw_ostream &O) override;
+  AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                      const char *ExtraCode,
+                                      raw_ostream &O) override;
+
+  void diagnoseAsmOperandError(LLVMContext &C, const AsmOperandErrorCode EC,
+                               const char *AsmStr, const uint64_t Loc) override;
+
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
                              const char *ExtraCode, raw_ostream &O) override;
 
diff --git a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp
index 363ab0efdeb91c..9b8193d30ea449 100644
--- a/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp
+++ b/llvm/lib/Target/XCore/XCoreAsmPrinter.cpp
@@ -66,8 +66,9 @@ namespace {
       printInlineJT(MI, opNum, O, ".jmptable32");
     }
     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
-    bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                         const char *ExtraCode, raw_ostream &O) override;
+    AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                        const char *ExtraCode,
+                                        raw_ostream &O) override;
     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                                const char *ExtraCode, raw_ostream &O) override;
 
@@ -229,12 +230,14 @@ void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
 
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
-bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                                      const char *ExtraCode, raw_ostream &O) {
+AsmOperandErrorCode XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
+                                                     unsigned OpNo,
+                                                     const char *ExtraCode,
+                                                     raw_ostream &O) {
   // Print the operand if there is no operand modifier.
   if (!ExtraCode || !ExtraCode[0]) {
     printOperand(MI, OpNo, O);
-    return false;
+    return AsmOperandErrorCode::NO_ERROR;
   }
 
   // Otherwise fallback on the default implementation.

>From 1d798db76d8ddbf4ddafbb1bcb1a857a66ed460a Mon Sep 17 00:00:00 2001
From: mahesh-attarde <mahesh.attarde at intel.com>
Date: Wed, 10 Apr 2024 00:54:24 -0700
Subject: [PATCH 2/2] sparc inline asm test fix

---
 llvm/lib/Target/Sparc/SparcAsmPrinter.cpp | 32 ++++++++++++++++-------
 llvm/test/CodeGen/SPARC/inlineasm-bad.ll  | 15 ++++++++++-
 2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
index ae20ab4e293a2b..2073795be0c5fb 100644
--- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -59,6 +59,8 @@ namespace {
     static const char *getRegisterName(MCRegister Reg) {
       return SparcInstPrinter::getRegisterName(Reg);
     }
+    void diagnoseAsmOperandError(LLVMContext &C, const AsmOperandErrorCode EC,
+                                 const char *AsmStr, uint64_t Loc) override;
 
     AsmOperandErrorCode PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                         const char *ExtraCode,
@@ -423,6 +425,25 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
   printOperand(MI, opNum+1, O);
 }
 
+void SparcAsmPrinter::diagnoseAsmOperandError(LLVMContext &C,
+                                              const AsmOperandErrorCode EC,
+                                              const char *AsmStr,
+                                              uint64_t Loc) {
+  AsmPrinter::diagnoseAsmOperandError(C, EC, AsmStr, Loc);
+  std::string msg;
+  raw_string_ostream Msg(msg);
+  switch (EC) {
+  default:
+    break;
+  case AsmOperandErrorCode::CONSTRAINT_H_ERROR:
+    Msg << "Hi part of pair should point to an even-numbered register";
+    Msg << "\n (note that in some cases it might be necessary to manually "
+           "bind the input/output registers instead of relying on "
+           "automatic allocation)";
+    break;
+  }
+  C.emitError(Msg.str());
+}
 /// PrintAsmOperand - Print out an operand for an inline asm expression.
 ///
 AsmOperandErrorCode SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
@@ -454,14 +475,7 @@ AsmOperandErrorCode SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
         MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
                                                   &SP::IntPairRegClass);
         if (!MOReg) {
-          SMLoc Loc;
-          OutContext.reportError(
-              Loc, "Hi part of pair should point to an even-numbered register");
-          OutContext.reportError(
-              Loc, "(note that in some cases it might be necessary to manually "
-                   "bind the input/output registers instead of relying on "
-                   "automatic allocation)");
-          return true;
+          return AsmOperandErrorCode::CONSTRAINT_H_ERROR;
         }
       }
 
@@ -479,7 +493,7 @@ AsmOperandErrorCode SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
       }
 
       O << '%' << SparcInstPrinter::getRegisterName(Reg);
-      return false;
+      return AsmOperandErrorCode::NO_ERROR;
     }
     case 'f':
     case 'r':
diff --git a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
index 07eb67df6e5f7e..7bb2fc798d2d88 100644
--- a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
+++ b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
 ; RUN: not llc -march=sparc <%s 2>&1 | FileCheck %s
 ; RUN: not llc -march=sparcv9 <%s 2>&1 | FileCheck %s
 
@@ -13,8 +14,20 @@ entry:
 }
 
 ; CHECK-label:test_twinword_error
+; CHECK: error: invalid operand in inline asm: 'rd %asr5, ${0:L}
+; CHECK: srlx ${0:L}, 32, ${0:H}'
 ; CHECK: error: Hi part of pair should point to an even-numbered register
-; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
+; CHECK: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
+
+; CHECK: error: invalid operand in inline asm: 'rd %asr5, ${0:L} 
+; CHECK: srlx ${0:L}, 32, ${0:H}'
+; CHECK: error: Hi part of pair should point to an even-numbered register
+; CHECK: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
+
+; CHECK: error: invalid operand in inline asm: 'rd %asr5, ${0:L} 
+; CHECK: srlx ${0:L}, 32, ${0:H}'
+; CHECK: error: Hi part of pair should point to an even-numbered register 
+; CHECK: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
 
 define i64 @test_twinword_error(){
   %1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"()



More information about the llvm-commits mailing list