diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 133 |
1 files changed, 125 insertions, 8 deletions
diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index 2b815a366ccd..0de24245cfcc 100644 --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -7,11 +7,13 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/SystemZInstPrinter.h" +#include "MCTargetDesc/SystemZMCAsmInfo.h" #include "MCTargetDesc/SystemZMCTargetDesc.h" #include "TargetInfo/SystemZTargetInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -428,6 +430,42 @@ private: bool parseOperand(OperandVector &Operands, StringRef Mnemonic); + // Both the hlasm and att variants still rely on the basic gnu asm + // format with respect to inputs, clobbers, outputs etc. + // + // However, calling the overriden getAssemblerDialect() method in + // AsmParser is problematic. It either returns the AssemblerDialect field + // in the MCAsmInfo instance if the AssemblerDialect field in AsmParser is + // unset, otherwise it returns the private AssemblerDialect field in + // AsmParser. + // + // The problematic part is because, we forcibly set the inline asm dialect + // in the AsmParser instance in AsmPrinterInlineAsm.cpp. Soo any query + // to the overriden getAssemblerDialect function in AsmParser.cpp, will + // not return the assembler dialect set in the respective MCAsmInfo instance. + // + // For this purpose, we explicitly query the SystemZMCAsmInfo instance + // here, to get the "correct" assembler dialect, and use it in various + // functions. + unsigned getMAIAssemblerDialect() { + return Parser.getContext().getAsmInfo()->getAssemblerDialect(); + } + + // An alphabetic character in HLASM is a letter from 'A' through 'Z', + // or from 'a' through 'z', or '$', '_','#', or '@'. + inline bool isHLASMAlpha(char C) { + return isAlpha(C) || llvm::is_contained("_@#$", C); + } + + // A digit in HLASM is a number from 0 to 9. + inline bool isHLASMAlnum(char C) { return isHLASMAlpha(C) || isDigit(C); } + + // Are we parsing using the AD_HLASM dialect? + inline bool isParsingHLASM() { return getMAIAssemblerDialect() == AD_HLASM; } + + // Are we parsing using the AD_ATT dialect? + inline bool isParsingATT() { return getMAIAssemblerDialect() == AD_ATT; } + public: SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, @@ -455,6 +493,7 @@ public: OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) override; + bool isLabel(AsmToken &Token) override; // Used by the TableGen code to parse particular operand types. OperandMatchResultTy parseGR32(OperandVector &Operands) { @@ -791,7 +830,7 @@ SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterKind Kind) { } // Handle register names of the form %<prefix><number> - if (Parser.getTok().is(AsmToken::Percent)) { + if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) { if (parseRegister(Reg)) return MatchOperand_ParseFail; @@ -873,6 +912,9 @@ SystemZAsmParser::parseAnyRegister(OperandVector &Operands) { Operands.push_back(SystemZOperand::createImm(Register, StartLoc, EndLoc)); } else { + if (isParsingHLASM()) + return MatchOperand_NoMatch; + Register Reg; if (parseRegister(Reg)) return MatchOperand_ParseFail; @@ -980,7 +1022,7 @@ bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1, if (getLexer().is(AsmToken::LParen)) { Parser.Lex(); - if (getLexer().is(AsmToken::Percent)) { + if (isParsingATT() && getLexer().is(AsmToken::Percent)) { // Parse the first register. HaveReg1 = true; if (parseRegister(Reg1)) @@ -1023,7 +1065,7 @@ bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1, if (parseIntegerRegister(Reg2, RegGR)) return true; } else { - if (parseRegister(Reg2)) + if (isParsingATT() && parseRegister(Reg2)) return true; } } @@ -1325,7 +1367,7 @@ bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info, // Apply mnemonic aliases first, before doing anything else, in // case the target uses it. - applyMnemonicAliases(Name, getAvailableFeatures(), 0 /*VariantID*/); + applyMnemonicAliases(Name, getAvailableFeatures(), getMAIAssemblerDialect()); Operands.push_back(SystemZOperand::createToken(Name, NameLoc)); @@ -1339,10 +1381,38 @@ bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info, // Read any subsequent operands. while (getLexer().is(AsmToken::Comma)) { Parser.Lex(); + + if (isParsingHLASM() && getLexer().is(AsmToken::Space)) + return Error( + Parser.getTok().getLoc(), + "No space allowed between comma that separates operand entries"); + if (parseOperand(Operands, Name)) { return true; } } + + // Under the HLASM variant, we could have the remark field + // The remark field occurs after the operation entries + // There is a space that separates the operation entries and the + // remark field. + if (isParsingHLASM() && getTok().is(AsmToken::Space)) { + // We've confirmed that there is a Remark field. + StringRef Remark(getLexer().LexUntilEndOfStatement()); + Parser.Lex(); + + // If there is nothing after the space, then there is nothing to emit + // We could have a situation as this: + // " \n" + // After lexing above, we will have + // "\n" + // This isn't an explicit remark field, so we don't have to output + // this as a comment. + if (Remark.size()) + // Output the entire Remarks Field as a comment + getStreamer().AddComment(Remark); + } + if (getLexer().isNot(AsmToken::EndOfStatement)) { SMLoc Loc = getLexer().getLoc(); return Error(Loc, "unexpected token in argument list"); @@ -1380,7 +1450,7 @@ bool SystemZAsmParser::parseOperand(OperandVector &Operands, // a context-dependent parse routine, which gives the required register // class. The code is here to mop up other cases, like those where // the instruction isn't recognized. - if (Parser.getTok().is(AsmToken::Percent)) { + if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) { Register Reg; if (parseRegister(Reg)) return true; @@ -1428,9 +1498,11 @@ bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst Inst; unsigned MatchResult; + unsigned Dialect = getMAIAssemblerDialect(); + FeatureBitset MissingFeatures; - MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MissingFeatures, MatchingInlineAsm); + MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, + MatchingInlineAsm, Dialect); switch (MatchResult) { case Match_Success: Inst.setLoc(IDLoc); @@ -1467,7 +1539,7 @@ bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_MnemonicFail: { FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); std::string Suggestion = SystemZMnemonicSpellCheck( - ((SystemZOperand &)*Operands[0]).getToken(), FBS); + ((SystemZOperand &)*Operands[0]).getToken(), FBS, Dialect); return Error(IDLoc, "invalid instruction" + Suggestion, ((SystemZOperand &)*Operands[0]).getLocRange()); } @@ -1498,6 +1570,10 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal, // For consistency with the GNU assembler, treat immediates as offsets // from ".". if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { + if (isParsingHLASM()) { + Error(StartLoc, "Expected PC-relative expression"); + return MatchOperand_ParseFail; + } if (isOutOfRangeConstant(CE)) { Error(StartLoc, "offset out of range"); return MatchOperand_ParseFail; @@ -1570,6 +1646,47 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal, return MatchOperand_Success; } +bool SystemZAsmParser::isLabel(AsmToken &Token) { + if (isParsingATT()) + return true; + + // HLASM labels are ordinary symbols. + // An HLASM label always starts at column 1. + // An ordinary symbol syntax is laid out as follows: + // Rules: + // 1. Has to start with an "alphabetic character". Can be followed by up to + // 62 alphanumeric characters. An "alphabetic character", in this scenario, + // is a letter from 'A' through 'Z', or from 'a' through 'z', + // or '$', '_', '#', or '@' + // 2. Labels are case-insensitive. E.g. "lab123", "LAB123", "lAb123", etc. + // are all treated as the same symbol. However, the processing for the case + // folding will not be done in this function. + StringRef RawLabel = Token.getString(); + SMLoc Loc = Token.getLoc(); + + // An HLASM label cannot be empty. + if (!RawLabel.size()) + return !Error(Loc, "HLASM Label cannot be empty"); + + // An HLASM label cannot exceed greater than 63 characters. + if (RawLabel.size() > 63) + return !Error(Loc, "Maximum length for HLASM Label is 63 characters"); + + // A label must start with an "alphabetic character". + if (!isHLASMAlpha(RawLabel[0])) + return !Error(Loc, "HLASM Label has to start with an alphabetic " + "character or the underscore character"); + + // Now, we've established that the length is valid + // and the first character is alphabetic. + // Check whether remaining string is alphanumeric. + for (unsigned I = 1; I < RawLabel.size(); ++I) + if (!isHLASMAlnum(RawLabel[I])) + return !Error(Loc, "HLASM Label has to be alphanumeric"); + + return true; +} + // Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmParser() { RegisterMCAsmParser<SystemZAsmParser> X(getTheSystemZTarget()); |
