diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index 81c3e4be95e9f..3c29b0133c5fc 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 e5f506e5694da..989bbe4700621 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__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 d0ef3e5a19391..2aa7347ffc3ff 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 f6ccd0ecfdc89..cdc54ca545be8 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 052b231d62a3e..5b60a210d0858 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(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 b8b2718d293e6..5a3032ba6075f 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 642739a29d6b0..9fa0c2b7ecff7 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 33b4417aa9b80..0c66ed16340df 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 1c8213b668f71..003171a49cde8 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 c8849bd50464c..289efe677b255 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 7d121b8d24f05..39d4d5bcd49ec 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 379189512405a..497043b481260 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 d2f64ac9e90b0..d27c0c9b4ae77 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 b555c88596503..274ec7bd3f4ea 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 c66d9166828c1..ad7b0d518ad6d 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 27979a830b10e..869ae6896a11f 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 693456443c7a4..aca6d07baa9f2 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 f748450c170aa..59fcebb9604f9 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 7b4dbfef58c57..2951b8c297174 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 9cd2cbe89e461..eb525117db919 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 66b2b0de8d52a..4c131ed2ae9ab 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 0b55089385d79..f3804db1bb31d 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 9f31b72bbceb1..96fecd2d200ce 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 979d185a97f79..a469a5493c269 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 16942c6893a16..b4c837c30aaa0 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 9982a73ee914d..e4e09269b296a 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 1de4616fd5b77..f85c3b8180377 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 6855471840e9d..2073795be0c5f 100644 --- a/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp +++ b/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp @@ -59,9 +59,12 @@ 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; - 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; @@ -422,13 +425,34 @@ 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. /// -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: @@ -451,14 +475,7 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 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; } } @@ -476,7 +493,7 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, } O << '%' << SparcInstPrinter::getRegisterName(Reg); - return false; + return AsmOperandErrorCode::NO_ERROR; } case 'f': case 'r': @@ -486,7 +503,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 5696ae117d69f..000d6bece4366 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 303cce1a1b658..b1ef3ff1f65ac 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 bdbc29f984b4c..5d0ddab2ccb16 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 3524abba8990a..fc515df4b295c 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 6a544abe6ce83..e71178b745018 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 3395a13545e45..a0a8f0938883e 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 693021eca3295..0b69a12950a28 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 363ab0efdeb91..9b8193d30ea44 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. diff --git a/llvm/test/CodeGen/SPARC/inlineasm-bad.ll b/llvm/test/CodeGen/SPARC/inlineasm-bad.ll index 07eb67df6e5f7..7bb2fc798d2d8 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}"()