Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
35294 views
//===-- SystemZAsmParser.cpp - Parse SystemZ assembly instructions --------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MCTargetDesc/SystemZInstPrinter.h"9#include "MCTargetDesc/SystemZMCAsmInfo.h"10#include "MCTargetDesc/SystemZMCTargetDesc.h"11#include "SystemZTargetStreamer.h"12#include "TargetInfo/SystemZTargetInfo.h"13#include "llvm/ADT/STLExtras.h"14#include "llvm/ADT/SmallVector.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCExpr.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCInstBuilder.h"22#include "llvm/MC/MCInstrInfo.h"23#include "llvm/MC/MCParser/MCAsmLexer.h"24#include "llvm/MC/MCParser/MCAsmParser.h"25#include "llvm/MC/MCParser/MCAsmParserExtension.h"26#include "llvm/MC/MCParser/MCParsedAsmOperand.h"27#include "llvm/MC/MCParser/MCTargetAsmParser.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSubtargetInfo.h"30#include "llvm/MC/TargetRegistry.h"31#include "llvm/Support/Casting.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/SMLoc.h"34#include <algorithm>35#include <cassert>36#include <cstddef>37#include <cstdint>38#include <iterator>39#include <memory>40#include <string>4142using namespace llvm;4344// Return true if Expr is in the range [MinValue, MaxValue]. If AllowSymbol45// is true any MCExpr is accepted (address displacement).46static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue,47bool AllowSymbol = false) {48if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {49int64_t Value = CE->getValue();50return Value >= MinValue && Value <= MaxValue;51}52return AllowSymbol;53}5455namespace {5657enum RegisterKind {58GR32Reg,59GRH32Reg,60GR64Reg,61GR128Reg,62FP32Reg,63FP64Reg,64FP128Reg,65VR32Reg,66VR64Reg,67VR128Reg,68AR32Reg,69CR64Reg,70};7172enum MemoryKind {73BDMem,74BDXMem,75BDLMem,76BDRMem,77BDVMem78};7980class SystemZOperand : public MCParsedAsmOperand {81private:82enum OperandKind {83KindInvalid,84KindToken,85KindReg,86KindImm,87KindImmTLS,88KindMem89};9091OperandKind Kind;92SMLoc StartLoc, EndLoc;9394// A string of length Length, starting at Data.95struct TokenOp {96const char *Data;97unsigned Length;98};99100// LLVM register Num, which has kind Kind. In some ways it might be101// easier for this class to have a register bank (general, floating-point102// or access) and a raw register number (0-15). This would postpone the103// interpretation of the operand to the add*() methods and avoid the need104// for context-dependent parsing. However, we do things the current way105// because of the virtual getReg() method, which needs to distinguish106// between (say) %r0 used as a single register and %r0 used as a pair.107// Context-dependent parsing can also give us slightly better error108// messages when invalid pairs like %r1 are used.109struct RegOp {110RegisterKind Kind;111unsigned Num;112};113114// Base + Disp + Index, where Base and Index are LLVM registers or 0.115// MemKind says what type of memory this is and RegKind says what type116// the base register has (GR32Reg or GR64Reg). Length is the operand117// length for D(L,B)-style operands, otherwise it is null.118struct MemOp {119unsigned Base : 12;120unsigned Index : 12;121unsigned MemKind : 4;122unsigned RegKind : 4;123const MCExpr *Disp;124union {125const MCExpr *Imm;126unsigned Reg;127} Length;128};129130// Imm is an immediate operand, and Sym is an optional TLS symbol131// for use with a __tls_get_offset marker relocation.132struct ImmTLSOp {133const MCExpr *Imm;134const MCExpr *Sym;135};136137union {138TokenOp Token;139RegOp Reg;140const MCExpr *Imm;141ImmTLSOp ImmTLS;142MemOp Mem;143};144145void addExpr(MCInst &Inst, const MCExpr *Expr) const {146// Add as immediates when possible. Null MCExpr = 0.147if (!Expr)148Inst.addOperand(MCOperand::createImm(0));149else if (auto *CE = dyn_cast<MCConstantExpr>(Expr))150Inst.addOperand(MCOperand::createImm(CE->getValue()));151else152Inst.addOperand(MCOperand::createExpr(Expr));153}154155public:156SystemZOperand(OperandKind Kind, SMLoc StartLoc, SMLoc EndLoc)157: Kind(Kind), StartLoc(StartLoc), EndLoc(EndLoc) {}158159// Create particular kinds of operand.160static std::unique_ptr<SystemZOperand> createInvalid(SMLoc StartLoc,161SMLoc EndLoc) {162return std::make_unique<SystemZOperand>(KindInvalid, StartLoc, EndLoc);163}164165static std::unique_ptr<SystemZOperand> createToken(StringRef Str, SMLoc Loc) {166auto Op = std::make_unique<SystemZOperand>(KindToken, Loc, Loc);167Op->Token.Data = Str.data();168Op->Token.Length = Str.size();169return Op;170}171172static std::unique_ptr<SystemZOperand>173createReg(RegisterKind Kind, unsigned Num, SMLoc StartLoc, SMLoc EndLoc) {174auto Op = std::make_unique<SystemZOperand>(KindReg, StartLoc, EndLoc);175Op->Reg.Kind = Kind;176Op->Reg.Num = Num;177return Op;178}179180static std::unique_ptr<SystemZOperand>181createImm(const MCExpr *Expr, SMLoc StartLoc, SMLoc EndLoc) {182auto Op = std::make_unique<SystemZOperand>(KindImm, StartLoc, EndLoc);183Op->Imm = Expr;184return Op;185}186187static std::unique_ptr<SystemZOperand>188createMem(MemoryKind MemKind, RegisterKind RegKind, unsigned Base,189const MCExpr *Disp, unsigned Index, const MCExpr *LengthImm,190unsigned LengthReg, SMLoc StartLoc, SMLoc EndLoc) {191auto Op = std::make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc);192Op->Mem.MemKind = MemKind;193Op->Mem.RegKind = RegKind;194Op->Mem.Base = Base;195Op->Mem.Index = Index;196Op->Mem.Disp = Disp;197if (MemKind == BDLMem)198Op->Mem.Length.Imm = LengthImm;199if (MemKind == BDRMem)200Op->Mem.Length.Reg = LengthReg;201return Op;202}203204static std::unique_ptr<SystemZOperand>205createImmTLS(const MCExpr *Imm, const MCExpr *Sym,206SMLoc StartLoc, SMLoc EndLoc) {207auto Op = std::make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc);208Op->ImmTLS.Imm = Imm;209Op->ImmTLS.Sym = Sym;210return Op;211}212213// Token operands214bool isToken() const override {215return Kind == KindToken;216}217StringRef getToken() const {218assert(Kind == KindToken && "Not a token");219return StringRef(Token.Data, Token.Length);220}221222// Register operands.223bool isReg() const override {224return Kind == KindReg;225}226bool isReg(RegisterKind RegKind) const {227return Kind == KindReg && Reg.Kind == RegKind;228}229MCRegister getReg() const override {230assert(Kind == KindReg && "Not a register");231return Reg.Num;232}233234// Immediate operands.235bool isImm() const override {236return Kind == KindImm;237}238bool isImm(int64_t MinValue, int64_t MaxValue) const {239return Kind == KindImm && inRange(Imm, MinValue, MaxValue, true);240}241const MCExpr *getImm() const {242assert(Kind == KindImm && "Not an immediate");243return Imm;244}245246// Immediate operands with optional TLS symbol.247bool isImmTLS() const {248return Kind == KindImmTLS;249}250251const ImmTLSOp getImmTLS() const {252assert(Kind == KindImmTLS && "Not a TLS immediate");253return ImmTLS;254}255256// Memory operands.257bool isMem() const override {258return Kind == KindMem;259}260bool isMem(MemoryKind MemKind) const {261return (Kind == KindMem &&262(Mem.MemKind == MemKind ||263// A BDMem can be treated as a BDXMem in which the index264// register field is 0.265(Mem.MemKind == BDMem && MemKind == BDXMem)));266}267bool isMem(MemoryKind MemKind, RegisterKind RegKind) const {268return isMem(MemKind) && Mem.RegKind == RegKind;269}270bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const {271return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff, true);272}273bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const {274return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287, true);275}276bool isMemDisp12Len4(RegisterKind RegKind) const {277return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10);278}279bool isMemDisp12Len8(RegisterKind RegKind) const {280return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x100);281}282283const MemOp& getMem() const {284assert(Kind == KindMem && "Not a Mem operand");285return Mem;286}287288// Override MCParsedAsmOperand.289SMLoc getStartLoc() const override { return StartLoc; }290SMLoc getEndLoc() const override { return EndLoc; }291void print(raw_ostream &OS) const override;292293/// getLocRange - Get the range between the first and last token of this294/// operand.295SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }296297// Used by the TableGen code to add particular types of operand298// to an instruction.299void addRegOperands(MCInst &Inst, unsigned N) const {300assert(N == 1 && "Invalid number of operands");301Inst.addOperand(MCOperand::createReg(getReg()));302}303void addImmOperands(MCInst &Inst, unsigned N) const {304assert(N == 1 && "Invalid number of operands");305addExpr(Inst, getImm());306}307void addBDAddrOperands(MCInst &Inst, unsigned N) const {308assert(N == 2 && "Invalid number of operands");309assert(isMem(BDMem) && "Invalid operand type");310Inst.addOperand(MCOperand::createReg(Mem.Base));311addExpr(Inst, Mem.Disp);312}313void addBDXAddrOperands(MCInst &Inst, unsigned N) const {314assert(N == 3 && "Invalid number of operands");315assert(isMem(BDXMem) && "Invalid operand type");316Inst.addOperand(MCOperand::createReg(Mem.Base));317addExpr(Inst, Mem.Disp);318Inst.addOperand(MCOperand::createReg(Mem.Index));319}320void addBDLAddrOperands(MCInst &Inst, unsigned N) const {321assert(N == 3 && "Invalid number of operands");322assert(isMem(BDLMem) && "Invalid operand type");323Inst.addOperand(MCOperand::createReg(Mem.Base));324addExpr(Inst, Mem.Disp);325addExpr(Inst, Mem.Length.Imm);326}327void addBDRAddrOperands(MCInst &Inst, unsigned N) const {328assert(N == 3 && "Invalid number of operands");329assert(isMem(BDRMem) && "Invalid operand type");330Inst.addOperand(MCOperand::createReg(Mem.Base));331addExpr(Inst, Mem.Disp);332Inst.addOperand(MCOperand::createReg(Mem.Length.Reg));333}334void addBDVAddrOperands(MCInst &Inst, unsigned N) const {335assert(N == 3 && "Invalid number of operands");336assert(isMem(BDVMem) && "Invalid operand type");337Inst.addOperand(MCOperand::createReg(Mem.Base));338addExpr(Inst, Mem.Disp);339Inst.addOperand(MCOperand::createReg(Mem.Index));340}341void addImmTLSOperands(MCInst &Inst, unsigned N) const {342assert(N == 2 && "Invalid number of operands");343assert(Kind == KindImmTLS && "Invalid operand type");344addExpr(Inst, ImmTLS.Imm);345if (ImmTLS.Sym)346addExpr(Inst, ImmTLS.Sym);347}348349// Used by the TableGen code to check for particular operand types.350bool isGR32() const { return isReg(GR32Reg); }351bool isGRH32() const { return isReg(GRH32Reg); }352bool isGRX32() const { return false; }353bool isGR64() const { return isReg(GR64Reg); }354bool isGR128() const { return isReg(GR128Reg); }355bool isADDR32() const { return isReg(GR32Reg); }356bool isADDR64() const { return isReg(GR64Reg); }357bool isADDR128() const { return false; }358bool isFP32() const { return isReg(FP32Reg); }359bool isFP64() const { return isReg(FP64Reg); }360bool isFP128() const { return isReg(FP128Reg); }361bool isVR32() const { return isReg(VR32Reg); }362bool isVR64() const { return isReg(VR64Reg); }363bool isVF128() const { return false; }364bool isVR128() const { return isReg(VR128Reg); }365bool isAR32() const { return isReg(AR32Reg); }366bool isCR64() const { return isReg(CR64Reg); }367bool isAnyReg() const { return (isReg() || isImm(0, 15)); }368bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, GR32Reg); }369bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, GR32Reg); }370bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, GR64Reg); }371bool isBDAddr64Disp20() const { return isMemDisp20(BDMem, GR64Reg); }372bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, GR64Reg); }373bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, GR64Reg); }374bool isBDLAddr64Disp12Len4() const { return isMemDisp12Len4(GR64Reg); }375bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(GR64Reg); }376bool isBDRAddr64Disp12() const { return isMemDisp12(BDRMem, GR64Reg); }377bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, GR64Reg); }378bool isU1Imm() const { return isImm(0, 1); }379bool isU2Imm() const { return isImm(0, 3); }380bool isU3Imm() const { return isImm(0, 7); }381bool isU4Imm() const { return isImm(0, 15); }382bool isU8Imm() const { return isImm(0, 255); }383bool isS8Imm() const { return isImm(-128, 127); }384bool isU12Imm() const { return isImm(0, 4095); }385bool isU16Imm() const { return isImm(0, 65535); }386bool isS16Imm() const { return isImm(-32768, 32767); }387bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); }388bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); }389bool isU48Imm() const { return isImm(0, (1LL << 48) - 1); }390};391392class SystemZAsmParser : public MCTargetAsmParser {393#define GET_ASSEMBLER_HEADER394#include "SystemZGenAsmMatcher.inc"395396private:397MCAsmParser &Parser;398enum RegisterGroup {399RegGR,400RegFP,401RegV,402RegAR,403RegCR404};405struct Register {406RegisterGroup Group;407unsigned Num;408SMLoc StartLoc, EndLoc;409};410411SystemZTargetStreamer &getTargetStreamer() {412assert(getParser().getStreamer().getTargetStreamer() &&413"do not have a target streamer");414MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();415return static_cast<SystemZTargetStreamer &>(TS);416}417418bool parseRegister(Register &Reg, bool RestoreOnFailure = false);419420bool parseIntegerRegister(Register &Reg, RegisterGroup Group);421422ParseStatus parseRegister(OperandVector &Operands, RegisterKind Kind);423424ParseStatus parseAnyRegister(OperandVector &Operands);425426bool parseAddress(bool &HaveReg1, Register &Reg1, bool &HaveReg2,427Register &Reg2, const MCExpr *&Disp, const MCExpr *&Length,428bool HasLength = false, bool HasVectorIndex = false);429bool parseAddressRegister(Register &Reg);430431bool ParseDirectiveInsn(SMLoc L);432bool ParseDirectiveMachine(SMLoc L);433bool ParseGNUAttribute(SMLoc L);434435ParseStatus parseAddress(OperandVector &Operands, MemoryKind MemKind,436RegisterKind RegKind);437438ParseStatus parsePCRel(OperandVector &Operands, int64_t MinVal,439int64_t MaxVal, bool AllowTLS);440441bool parseOperand(OperandVector &Operands, StringRef Mnemonic);442443// Both the hlasm and att variants still rely on the basic gnu asm444// format with respect to inputs, clobbers, outputs etc.445//446// However, calling the overriden getAssemblerDialect() method in447// AsmParser is problematic. It either returns the AssemblerDialect field448// in the MCAsmInfo instance if the AssemblerDialect field in AsmParser is449// unset, otherwise it returns the private AssemblerDialect field in450// AsmParser.451//452// The problematic part is because, we forcibly set the inline asm dialect453// in the AsmParser instance in AsmPrinterInlineAsm.cpp. Soo any query454// to the overriden getAssemblerDialect function in AsmParser.cpp, will455// not return the assembler dialect set in the respective MCAsmInfo instance.456//457// For this purpose, we explicitly query the SystemZMCAsmInfo instance458// here, to get the "correct" assembler dialect, and use it in various459// functions.460unsigned getMAIAssemblerDialect() {461return Parser.getContext().getAsmInfo()->getAssemblerDialect();462}463464// An alphabetic character in HLASM is a letter from 'A' through 'Z',465// or from 'a' through 'z', or '$', '_','#', or '@'.466inline bool isHLASMAlpha(char C) {467return isAlpha(C) || llvm::is_contained("_@#$", C);468}469470// A digit in HLASM is a number from 0 to 9.471inline bool isHLASMAlnum(char C) { return isHLASMAlpha(C) || isDigit(C); }472473// Are we parsing using the AD_HLASM dialect?474inline bool isParsingHLASM() { return getMAIAssemblerDialect() == AD_HLASM; }475476// Are we parsing using the AD_ATT dialect?477inline bool isParsingATT() { return getMAIAssemblerDialect() == AD_ATT; }478479public:480SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,481const MCInstrInfo &MII,482const MCTargetOptions &Options)483: MCTargetAsmParser(Options, sti, MII), Parser(parser) {484MCAsmParserExtension::Initialize(Parser);485486// Alias the .word directive to .short.487parser.addAliasForDirective(".word", ".short");488489// Initialize the set of available features.490setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));491}492493// Override MCTargetAsmParser.494ParseStatus parseDirective(AsmToken DirectiveID) override;495bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;496bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,497bool RestoreOnFailure);498ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,499SMLoc &EndLoc) override;500bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,501SMLoc NameLoc, OperandVector &Operands) override;502bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,503OperandVector &Operands, MCStreamer &Out,504uint64_t &ErrorInfo,505bool MatchingInlineAsm) override;506bool isLabel(AsmToken &Token) override;507508// Used by the TableGen code to parse particular operand types.509ParseStatus parseGR32(OperandVector &Operands) {510return parseRegister(Operands, GR32Reg);511}512ParseStatus parseGRH32(OperandVector &Operands) {513return parseRegister(Operands, GRH32Reg);514}515ParseStatus parseGRX32(OperandVector &Operands) {516llvm_unreachable("GRX32 should only be used for pseudo instructions");517}518ParseStatus parseGR64(OperandVector &Operands) {519return parseRegister(Operands, GR64Reg);520}521ParseStatus parseGR128(OperandVector &Operands) {522return parseRegister(Operands, GR128Reg);523}524ParseStatus parseADDR32(OperandVector &Operands) {525// For the AsmParser, we will accept %r0 for ADDR32 as well.526return parseRegister(Operands, GR32Reg);527}528ParseStatus parseADDR64(OperandVector &Operands) {529// For the AsmParser, we will accept %r0 for ADDR64 as well.530return parseRegister(Operands, GR64Reg);531}532ParseStatus parseADDR128(OperandVector &Operands) {533llvm_unreachable("Shouldn't be used as an operand");534}535ParseStatus parseFP32(OperandVector &Operands) {536return parseRegister(Operands, FP32Reg);537}538ParseStatus parseFP64(OperandVector &Operands) {539return parseRegister(Operands, FP64Reg);540}541ParseStatus parseFP128(OperandVector &Operands) {542return parseRegister(Operands, FP128Reg);543}544ParseStatus parseVR32(OperandVector &Operands) {545return parseRegister(Operands, VR32Reg);546}547ParseStatus parseVR64(OperandVector &Operands) {548return parseRegister(Operands, VR64Reg);549}550ParseStatus parseVF128(OperandVector &Operands) {551llvm_unreachable("Shouldn't be used as an operand");552}553ParseStatus parseVR128(OperandVector &Operands) {554return parseRegister(Operands, VR128Reg);555}556ParseStatus parseAR32(OperandVector &Operands) {557return parseRegister(Operands, AR32Reg);558}559ParseStatus parseCR64(OperandVector &Operands) {560return parseRegister(Operands, CR64Reg);561}562ParseStatus parseAnyReg(OperandVector &Operands) {563return parseAnyRegister(Operands);564}565ParseStatus parseBDAddr32(OperandVector &Operands) {566return parseAddress(Operands, BDMem, GR32Reg);567}568ParseStatus parseBDAddr64(OperandVector &Operands) {569return parseAddress(Operands, BDMem, GR64Reg);570}571ParseStatus parseBDXAddr64(OperandVector &Operands) {572return parseAddress(Operands, BDXMem, GR64Reg);573}574ParseStatus parseBDLAddr64(OperandVector &Operands) {575return parseAddress(Operands, BDLMem, GR64Reg);576}577ParseStatus parseBDRAddr64(OperandVector &Operands) {578return parseAddress(Operands, BDRMem, GR64Reg);579}580ParseStatus parseBDVAddr64(OperandVector &Operands) {581return parseAddress(Operands, BDVMem, GR64Reg);582}583ParseStatus parsePCRel12(OperandVector &Operands) {584return parsePCRel(Operands, -(1LL << 12), (1LL << 12) - 1, false);585}586ParseStatus parsePCRel16(OperandVector &Operands) {587return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false);588}589ParseStatus parsePCRel24(OperandVector &Operands) {590return parsePCRel(Operands, -(1LL << 24), (1LL << 24) - 1, false);591}592ParseStatus parsePCRel32(OperandVector &Operands) {593return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false);594}595ParseStatus parsePCRelTLS16(OperandVector &Operands) {596return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true);597}598ParseStatus parsePCRelTLS32(OperandVector &Operands) {599return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true);600}601};602603} // end anonymous namespace604605#define GET_REGISTER_MATCHER606#define GET_SUBTARGET_FEATURE_NAME607#define GET_MATCHER_IMPLEMENTATION608#define GET_MNEMONIC_SPELL_CHECKER609#include "SystemZGenAsmMatcher.inc"610611// Used for the .insn directives; contains information needed to parse the612// operands in the directive.613struct InsnMatchEntry {614StringRef Format;615uint64_t Opcode;616int32_t NumOperands;617MatchClassKind OperandKinds[7];618};619620// For equal_range comparison.621struct CompareInsn {622bool operator() (const InsnMatchEntry &LHS, StringRef RHS) {623return LHS.Format < RHS;624}625bool operator() (StringRef LHS, const InsnMatchEntry &RHS) {626return LHS < RHS.Format;627}628bool operator() (const InsnMatchEntry &LHS, const InsnMatchEntry &RHS) {629return LHS.Format < RHS.Format;630}631};632633// Table initializing information for parsing the .insn directive.634static struct InsnMatchEntry InsnMatchTable[] = {635/* Format, Opcode, NumOperands, OperandKinds */636{ "e", SystemZ::InsnE, 1,637{ MCK_U16Imm } },638{ "ri", SystemZ::InsnRI, 3,639{ MCK_U32Imm, MCK_AnyReg, MCK_S16Imm } },640{ "rie", SystemZ::InsnRIE, 4,641{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },642{ "ril", SystemZ::InsnRIL, 3,643{ MCK_U48Imm, MCK_AnyReg, MCK_PCRel32 } },644{ "rilu", SystemZ::InsnRILU, 3,645{ MCK_U48Imm, MCK_AnyReg, MCK_U32Imm } },646{ "ris", SystemZ::InsnRIS, 5,647{ MCK_U48Imm, MCK_AnyReg, MCK_S8Imm, MCK_U4Imm, MCK_BDAddr64Disp12 } },648{ "rr", SystemZ::InsnRR, 3,649{ MCK_U16Imm, MCK_AnyReg, MCK_AnyReg } },650{ "rre", SystemZ::InsnRRE, 3,651{ MCK_U32Imm, MCK_AnyReg, MCK_AnyReg } },652{ "rrf", SystemZ::InsnRRF, 5,653{ MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm } },654{ "rrs", SystemZ::InsnRRS, 5,655{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm, MCK_BDAddr64Disp12 } },656{ "rs", SystemZ::InsnRS, 4,657{ MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },658{ "rse", SystemZ::InsnRSE, 4,659{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } },660{ "rsi", SystemZ::InsnRSI, 4,661{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } },662{ "rsy", SystemZ::InsnRSY, 4,663{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp20 } },664{ "rx", SystemZ::InsnRX, 3,665{ MCK_U32Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },666{ "rxe", SystemZ::InsnRXE, 3,667{ MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } },668{ "rxf", SystemZ::InsnRXF, 4,669{ MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDXAddr64Disp12 } },670{ "rxy", SystemZ::InsnRXY, 3,671{ MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp20 } },672{ "s", SystemZ::InsnS, 2,673{ MCK_U32Imm, MCK_BDAddr64Disp12 } },674{ "si", SystemZ::InsnSI, 3,675{ MCK_U32Imm, MCK_BDAddr64Disp12, MCK_S8Imm } },676{ "sil", SystemZ::InsnSIL, 3,677{ MCK_U48Imm, MCK_BDAddr64Disp12, MCK_U16Imm } },678{ "siy", SystemZ::InsnSIY, 3,679{ MCK_U48Imm, MCK_BDAddr64Disp20, MCK_U8Imm } },680{ "ss", SystemZ::InsnSS, 4,681{ MCK_U48Imm, MCK_BDXAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },682{ "sse", SystemZ::InsnSSE, 3,683{ MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12 } },684{ "ssf", SystemZ::InsnSSF, 4,685{ MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } },686{ "vri", SystemZ::InsnVRI, 6,687{ MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_U12Imm, MCK_U4Imm, MCK_U4Imm } },688{ "vrr", SystemZ::InsnVRR, 7,689{ MCK_U48Imm, MCK_VR128, MCK_VR128, MCK_VR128, MCK_U4Imm, MCK_U4Imm,690MCK_U4Imm } },691{ "vrs", SystemZ::InsnVRS, 5,692{ MCK_U48Imm, MCK_AnyReg, MCK_VR128, MCK_BDAddr64Disp12, MCK_U4Imm } },693{ "vrv", SystemZ::InsnVRV, 4,694{ MCK_U48Imm, MCK_VR128, MCK_BDVAddr64Disp12, MCK_U4Imm } },695{ "vrx", SystemZ::InsnVRX, 4,696{ MCK_U48Imm, MCK_VR128, MCK_BDXAddr64Disp12, MCK_U4Imm } },697{ "vsi", SystemZ::InsnVSI, 4,698{ MCK_U48Imm, MCK_VR128, MCK_BDAddr64Disp12, MCK_U8Imm } }699};700701static void printMCExpr(const MCExpr *E, raw_ostream &OS) {702if (!E)703return;704if (auto *CE = dyn_cast<MCConstantExpr>(E))705OS << *CE;706else if (auto *UE = dyn_cast<MCUnaryExpr>(E))707OS << *UE;708else if (auto *BE = dyn_cast<MCBinaryExpr>(E))709OS << *BE;710else if (auto *SRE = dyn_cast<MCSymbolRefExpr>(E))711OS << *SRE;712else713OS << *E;714}715716void SystemZOperand::print(raw_ostream &OS) const {717switch (Kind) {718case KindToken:719OS << "Token:" << getToken();720break;721case KindReg:722OS << "Reg:" << SystemZInstPrinter::getRegisterName(getReg());723break;724case KindImm:725OS << "Imm:";726printMCExpr(getImm(), OS);727break;728case KindImmTLS:729OS << "ImmTLS:";730printMCExpr(getImmTLS().Imm, OS);731if (getImmTLS().Sym) {732OS << ", ";733printMCExpr(getImmTLS().Sym, OS);734}735break;736case KindMem: {737const MemOp &Op = getMem();738OS << "Mem:" << *cast<MCConstantExpr>(Op.Disp);739if (Op.Base) {740OS << "(";741if (Op.MemKind == BDLMem)742OS << *cast<MCConstantExpr>(Op.Length.Imm) << ",";743else if (Op.MemKind == BDRMem)744OS << SystemZInstPrinter::getRegisterName(Op.Length.Reg) << ",";745if (Op.Index)746OS << SystemZInstPrinter::getRegisterName(Op.Index) << ",";747OS << SystemZInstPrinter::getRegisterName(Op.Base);748OS << ")";749}750break;751}752case KindInvalid:753break;754}755}756757// Parse one register of the form %<prefix><number>.758bool SystemZAsmParser::parseRegister(Register &Reg, bool RestoreOnFailure) {759Reg.StartLoc = Parser.getTok().getLoc();760761// Eat the % prefix.762if (Parser.getTok().isNot(AsmToken::Percent))763return Error(Parser.getTok().getLoc(), "register expected");764const AsmToken &PercentTok = Parser.getTok();765Parser.Lex();766767// Expect a register name.768if (Parser.getTok().isNot(AsmToken::Identifier)) {769if (RestoreOnFailure)770getLexer().UnLex(PercentTok);771return Error(Reg.StartLoc, "invalid register");772}773774// Check that there's a prefix.775StringRef Name = Parser.getTok().getString();776if (Name.size() < 2) {777if (RestoreOnFailure)778getLexer().UnLex(PercentTok);779return Error(Reg.StartLoc, "invalid register");780}781char Prefix = Name[0];782783// Treat the rest of the register name as a register number.784if (Name.substr(1).getAsInteger(10, Reg.Num)) {785if (RestoreOnFailure)786getLexer().UnLex(PercentTok);787return Error(Reg.StartLoc, "invalid register");788}789790// Look for valid combinations of prefix and number.791if (Prefix == 'r' && Reg.Num < 16)792Reg.Group = RegGR;793else if (Prefix == 'f' && Reg.Num < 16)794Reg.Group = RegFP;795else if (Prefix == 'v' && Reg.Num < 32)796Reg.Group = RegV;797else if (Prefix == 'a' && Reg.Num < 16)798Reg.Group = RegAR;799else if (Prefix == 'c' && Reg.Num < 16)800Reg.Group = RegCR;801else {802if (RestoreOnFailure)803getLexer().UnLex(PercentTok);804return Error(Reg.StartLoc, "invalid register");805}806807Reg.EndLoc = Parser.getTok().getLoc();808Parser.Lex();809return false;810}811812// Parse a register of kind Kind and add it to Operands.813ParseStatus SystemZAsmParser::parseRegister(OperandVector &Operands,814RegisterKind Kind) {815Register Reg;816RegisterGroup Group;817switch (Kind) {818case GR32Reg:819case GRH32Reg:820case GR64Reg:821case GR128Reg:822Group = RegGR;823break;824case FP32Reg:825case FP64Reg:826case FP128Reg:827Group = RegFP;828break;829case VR32Reg:830case VR64Reg:831case VR128Reg:832Group = RegV;833break;834case AR32Reg:835Group = RegAR;836break;837case CR64Reg:838Group = RegCR;839break;840}841842// Handle register names of the form %<prefix><number>843if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {844if (parseRegister(Reg))845return ParseStatus::Failure;846847// Check the parsed register group "Reg.Group" with the expected "Group"848// Have to error out if user specified wrong prefix.849switch (Group) {850case RegGR:851case RegFP:852case RegAR:853case RegCR:854if (Group != Reg.Group)855return Error(Reg.StartLoc, "invalid operand for instruction");856break;857case RegV:858if (Reg.Group != RegV && Reg.Group != RegFP)859return Error(Reg.StartLoc, "invalid operand for instruction");860break;861}862} else if (Parser.getTok().is(AsmToken::Integer)) {863if (parseIntegerRegister(Reg, Group))864return ParseStatus::Failure;865}866// Otherwise we didn't match a register operand.867else868return ParseStatus::NoMatch;869870// Determine the LLVM register number according to Kind.871const unsigned *Regs;872switch (Kind) {873case GR32Reg: Regs = SystemZMC::GR32Regs; break;874case GRH32Reg: Regs = SystemZMC::GRH32Regs; break;875case GR64Reg: Regs = SystemZMC::GR64Regs; break;876case GR128Reg: Regs = SystemZMC::GR128Regs; break;877case FP32Reg: Regs = SystemZMC::FP32Regs; break;878case FP64Reg: Regs = SystemZMC::FP64Regs; break;879case FP128Reg: Regs = SystemZMC::FP128Regs; break;880case VR32Reg: Regs = SystemZMC::VR32Regs; break;881case VR64Reg: Regs = SystemZMC::VR64Regs; break;882case VR128Reg: Regs = SystemZMC::VR128Regs; break;883case AR32Reg: Regs = SystemZMC::AR32Regs; break;884case CR64Reg: Regs = SystemZMC::CR64Regs; break;885}886if (Regs[Reg.Num] == 0)887return Error(Reg.StartLoc, "invalid register pair");888889Operands.push_back(890SystemZOperand::createReg(Kind, Regs[Reg.Num], Reg.StartLoc, Reg.EndLoc));891return ParseStatus::Success;892}893894// Parse any type of register (including integers) and add it to Operands.895ParseStatus SystemZAsmParser::parseAnyRegister(OperandVector &Operands) {896SMLoc StartLoc = Parser.getTok().getLoc();897898// Handle integer values.899if (Parser.getTok().is(AsmToken::Integer)) {900const MCExpr *Register;901if (Parser.parseExpression(Register))902return ParseStatus::Failure;903904if (auto *CE = dyn_cast<MCConstantExpr>(Register)) {905int64_t Value = CE->getValue();906if (Value < 0 || Value > 15)907return Error(StartLoc, "invalid register");908}909910SMLoc EndLoc =911SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);912913Operands.push_back(SystemZOperand::createImm(Register, StartLoc, EndLoc));914}915else {916if (isParsingHLASM())917return ParseStatus::NoMatch;918919Register Reg;920if (parseRegister(Reg))921return ParseStatus::Failure;922923if (Reg.Num > 15)924return Error(StartLoc, "invalid register");925926// Map to the correct register kind.927RegisterKind Kind;928unsigned RegNo;929if (Reg.Group == RegGR) {930Kind = GR64Reg;931RegNo = SystemZMC::GR64Regs[Reg.Num];932}933else if (Reg.Group == RegFP) {934Kind = FP64Reg;935RegNo = SystemZMC::FP64Regs[Reg.Num];936}937else if (Reg.Group == RegV) {938Kind = VR128Reg;939RegNo = SystemZMC::VR128Regs[Reg.Num];940}941else if (Reg.Group == RegAR) {942Kind = AR32Reg;943RegNo = SystemZMC::AR32Regs[Reg.Num];944}945else if (Reg.Group == RegCR) {946Kind = CR64Reg;947RegNo = SystemZMC::CR64Regs[Reg.Num];948}949else {950return ParseStatus::Failure;951}952953Operands.push_back(SystemZOperand::createReg(Kind, RegNo,954Reg.StartLoc, Reg.EndLoc));955}956return ParseStatus::Success;957}958959bool SystemZAsmParser::parseIntegerRegister(Register &Reg,960RegisterGroup Group) {961Reg.StartLoc = Parser.getTok().getLoc();962// We have an integer token963const MCExpr *Register;964if (Parser.parseExpression(Register))965return true;966967const auto *CE = dyn_cast<MCConstantExpr>(Register);968if (!CE)969return true;970971int64_t MaxRegNum = (Group == RegV) ? 31 : 15;972int64_t Value = CE->getValue();973if (Value < 0 || Value > MaxRegNum) {974Error(Parser.getTok().getLoc(), "invalid register");975return true;976}977978// Assign the Register Number979Reg.Num = (unsigned)Value;980Reg.Group = Group;981Reg.EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);982983// At this point, successfully parsed an integer register.984return false;985}986987// Parse a memory operand into Reg1, Reg2, Disp, and Length.988bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1,989bool &HaveReg2, Register &Reg2,990const MCExpr *&Disp, const MCExpr *&Length,991bool HasLength, bool HasVectorIndex) {992// Parse the displacement, which must always be present.993if (getParser().parseExpression(Disp))994return true;995996// Parse the optional base and index.997HaveReg1 = false;998HaveReg2 = false;999Length = nullptr;10001001// If we have a scenario as below:1002// vgef %v0, 0(0), 01003// This is an example of a "BDVMem" instruction type.1004//1005// So when we parse this as an integer register, the register group1006// needs to be tied to "RegV". Usually when the prefix is passed in1007// as %<prefix><reg-number> its easy to check which group it should belong to1008// However, if we're passing in just the integer there's no real way to1009// "check" what register group it should belong to.1010//1011// When the user passes in the register as an integer, the user assumes that1012// the compiler is responsible for substituting it as the right kind of1013// register. Whereas, when the user specifies a "prefix", the onus is on1014// the user to make sure they pass in the right kind of register.1015//1016// The restriction only applies to the first Register (i.e. Reg1). Reg2 is1017// always a general register. Reg1 should be of group RegV if "HasVectorIndex"1018// (i.e. insn is of type BDVMem) is true.1019RegisterGroup RegGroup = HasVectorIndex ? RegV : RegGR;10201021if (getLexer().is(AsmToken::LParen)) {1022Parser.Lex();10231024if (isParsingATT() && getLexer().is(AsmToken::Percent)) {1025// Parse the first register.1026HaveReg1 = true;1027if (parseRegister(Reg1))1028return true;1029}1030// So if we have an integer as the first token in ([tok1], ..), it could:1031// 1. Refer to a "Register" (i.e X,R,V fields in BD[X|R|V]Mem type of1032// instructions)1033// 2. Refer to a "Length" field (i.e L field in BDLMem type of instructions)1034else if (getLexer().is(AsmToken::Integer)) {1035if (HasLength) {1036// Instruction has a "Length" field, safe to parse the first token as1037// the "Length" field1038if (getParser().parseExpression(Length))1039return true;1040} else {1041// Otherwise, if the instruction has no "Length" field, parse the1042// token as a "Register". We don't have to worry about whether the1043// instruction is invalid here, because the caller will take care of1044// error reporting.1045HaveReg1 = true;1046if (parseIntegerRegister(Reg1, RegGroup))1047return true;1048}1049} else {1050// If its not an integer or a percent token, then if the instruction1051// is reported to have a "Length" then, parse it as "Length".1052if (HasLength) {1053if (getParser().parseExpression(Length))1054return true;1055}1056}10571058// Check whether there's a second register.1059if (getLexer().is(AsmToken::Comma)) {1060Parser.Lex();1061HaveReg2 = true;10621063if (getLexer().is(AsmToken::Integer)) {1064if (parseIntegerRegister(Reg2, RegGR))1065return true;1066} else {1067if (isParsingATT() && parseRegister(Reg2))1068return true;1069}1070}10711072// Consume the closing bracket.1073if (getLexer().isNot(AsmToken::RParen))1074return Error(Parser.getTok().getLoc(), "unexpected token in address");1075Parser.Lex();1076}1077return false;1078}10791080// Verify that Reg is a valid address register (base or index).1081bool1082SystemZAsmParser::parseAddressRegister(Register &Reg) {1083if (Reg.Group == RegV) {1084Error(Reg.StartLoc, "invalid use of vector addressing");1085return true;1086}1087if (Reg.Group != RegGR) {1088Error(Reg.StartLoc, "invalid address register");1089return true;1090}1091return false;1092}10931094// Parse a memory operand and add it to Operands. The other arguments1095// are as above.1096ParseStatus SystemZAsmParser::parseAddress(OperandVector &Operands,1097MemoryKind MemKind,1098RegisterKind RegKind) {1099SMLoc StartLoc = Parser.getTok().getLoc();1100unsigned Base = 0, Index = 0, LengthReg = 0;1101Register Reg1, Reg2;1102bool HaveReg1, HaveReg2;1103const MCExpr *Disp;1104const MCExpr *Length;11051106bool HasLength = (MemKind == BDLMem) ? true : false;1107bool HasVectorIndex = (MemKind == BDVMem) ? true : false;1108if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Disp, Length, HasLength,1109HasVectorIndex))1110return ParseStatus::Failure;11111112const unsigned *Regs;1113switch (RegKind) {1114case GR32Reg: Regs = SystemZMC::GR32Regs; break;1115case GR64Reg: Regs = SystemZMC::GR64Regs; break;1116default: llvm_unreachable("invalid RegKind");1117}11181119switch (MemKind) {1120case BDMem:1121// If we have Reg1, it must be an address register.1122if (HaveReg1) {1123if (parseAddressRegister(Reg1))1124return ParseStatus::Failure;1125Base = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];1126}1127// There must be no Reg2.1128if (HaveReg2)1129return Error(StartLoc, "invalid use of indexed addressing");1130break;1131case BDXMem:1132// If we have Reg1, it must be an address register.1133if (HaveReg1) {1134if (parseAddressRegister(Reg1))1135return ParseStatus::Failure;1136// If the are two registers, the first one is the index and the1137// second is the base.1138if (HaveReg2)1139Index = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];1140else1141Base = Reg1.Num == 0 ? 0 : Regs[Reg1.Num];1142}1143// If we have Reg2, it must be an address register.1144if (HaveReg2) {1145if (parseAddressRegister(Reg2))1146return ParseStatus::Failure;1147Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];1148}1149break;1150case BDLMem:1151// If we have Reg2, it must be an address register.1152if (HaveReg2) {1153if (parseAddressRegister(Reg2))1154return ParseStatus::Failure;1155Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];1156}1157// We cannot support base+index addressing.1158if (HaveReg1 && HaveReg2)1159return Error(StartLoc, "invalid use of indexed addressing");1160// We must have a length.1161if (!Length)1162return Error(StartLoc, "missing length in address");1163break;1164case BDRMem:1165// We must have Reg1, and it must be a GPR.1166if (!HaveReg1 || Reg1.Group != RegGR)1167return Error(StartLoc, "invalid operand for instruction");1168LengthReg = SystemZMC::GR64Regs[Reg1.Num];1169// If we have Reg2, it must be an address register.1170if (HaveReg2) {1171if (parseAddressRegister(Reg2))1172return ParseStatus::Failure;1173Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];1174}1175break;1176case BDVMem:1177// We must have Reg1, and it must be a vector register.1178if (!HaveReg1 || Reg1.Group != RegV)1179return Error(StartLoc, "vector index required in address");1180Index = SystemZMC::VR128Regs[Reg1.Num];1181// If we have Reg2, it must be an address register.1182if (HaveReg2) {1183if (parseAddressRegister(Reg2))1184return ParseStatus::Failure;1185Base = Reg2.Num == 0 ? 0 : Regs[Reg2.Num];1186}1187break;1188}11891190SMLoc EndLoc =1191SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);1192Operands.push_back(SystemZOperand::createMem(MemKind, RegKind, Base, Disp,1193Index, Length, LengthReg,1194StartLoc, EndLoc));1195return ParseStatus::Success;1196}11971198ParseStatus SystemZAsmParser::parseDirective(AsmToken DirectiveID) {1199StringRef IDVal = DirectiveID.getIdentifier();12001201if (IDVal == ".insn")1202return ParseDirectiveInsn(DirectiveID.getLoc());1203if (IDVal == ".machine")1204return ParseDirectiveMachine(DirectiveID.getLoc());1205if (IDVal.starts_with(".gnu_attribute"))1206return ParseGNUAttribute(DirectiveID.getLoc());12071208return ParseStatus::NoMatch;1209}12101211/// ParseDirectiveInsn1212/// ::= .insn [ format, encoding, (operands (, operands)*) ]1213bool SystemZAsmParser::ParseDirectiveInsn(SMLoc L) {1214MCAsmParser &Parser = getParser();12151216// Expect instruction format as identifier.1217StringRef Format;1218SMLoc ErrorLoc = Parser.getTok().getLoc();1219if (Parser.parseIdentifier(Format))1220return Error(ErrorLoc, "expected instruction format");12211222SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;12231224// Find entry for this format in InsnMatchTable.1225auto EntryRange =1226std::equal_range(std::begin(InsnMatchTable), std::end(InsnMatchTable),1227Format, CompareInsn());12281229// If first == second, couldn't find a match in the table.1230if (EntryRange.first == EntryRange.second)1231return Error(ErrorLoc, "unrecognized format");12321233struct InsnMatchEntry *Entry = EntryRange.first;12341235// Format should match from equal_range.1236assert(Entry->Format == Format);12371238// Parse the following operands using the table's information.1239for (int I = 0; I < Entry->NumOperands; I++) {1240MatchClassKind Kind = Entry->OperandKinds[I];12411242SMLoc StartLoc = Parser.getTok().getLoc();12431244// Always expect commas as separators for operands.1245if (getLexer().isNot(AsmToken::Comma))1246return Error(StartLoc, "unexpected token in directive");1247Lex();12481249// Parse operands.1250ParseStatus ResTy;1251if (Kind == MCK_AnyReg)1252ResTy = parseAnyReg(Operands);1253else if (Kind == MCK_VR128)1254ResTy = parseVR128(Operands);1255else if (Kind == MCK_BDXAddr64Disp12 || Kind == MCK_BDXAddr64Disp20)1256ResTy = parseBDXAddr64(Operands);1257else if (Kind == MCK_BDAddr64Disp12 || Kind == MCK_BDAddr64Disp20)1258ResTy = parseBDAddr64(Operands);1259else if (Kind == MCK_BDVAddr64Disp12)1260ResTy = parseBDVAddr64(Operands);1261else if (Kind == MCK_PCRel32)1262ResTy = parsePCRel32(Operands);1263else if (Kind == MCK_PCRel16)1264ResTy = parsePCRel16(Operands);1265else {1266// Only remaining operand kind is an immediate.1267const MCExpr *Expr;1268SMLoc StartLoc = Parser.getTok().getLoc();12691270// Expect immediate expression.1271if (Parser.parseExpression(Expr))1272return Error(StartLoc, "unexpected token in directive");12731274SMLoc EndLoc =1275SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);12761277Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));1278ResTy = ParseStatus::Success;1279}12801281if (!ResTy.isSuccess())1282return true;1283}12841285// Build the instruction with the parsed operands.1286MCInst Inst = MCInstBuilder(Entry->Opcode);12871288for (size_t I = 0; I < Operands.size(); I++) {1289MCParsedAsmOperand &Operand = *Operands[I];1290MatchClassKind Kind = Entry->OperandKinds[I];12911292// Verify operand.1293unsigned Res = validateOperandClass(Operand, Kind);1294if (Res != Match_Success)1295return Error(Operand.getStartLoc(), "unexpected operand type");12961297// Add operands to instruction.1298SystemZOperand &ZOperand = static_cast<SystemZOperand &>(Operand);1299if (ZOperand.isReg())1300ZOperand.addRegOperands(Inst, 1);1301else if (ZOperand.isMem(BDMem))1302ZOperand.addBDAddrOperands(Inst, 2);1303else if (ZOperand.isMem(BDXMem))1304ZOperand.addBDXAddrOperands(Inst, 3);1305else if (ZOperand.isMem(BDVMem))1306ZOperand.addBDVAddrOperands(Inst, 3);1307else if (ZOperand.isImm())1308ZOperand.addImmOperands(Inst, 1);1309else1310llvm_unreachable("unexpected operand type");1311}13121313// Emit as a regular instruction.1314Parser.getStreamer().emitInstruction(Inst, getSTI());13151316return false;1317}13181319/// ParseDirectiveMachine1320/// ::= .machine [ mcpu ]1321bool SystemZAsmParser::ParseDirectiveMachine(SMLoc L) {1322MCAsmParser &Parser = getParser();1323if (Parser.getTok().isNot(AsmToken::Identifier) &&1324Parser.getTok().isNot(AsmToken::String))1325return TokError("unexpected token in '.machine' directive");13261327StringRef CPU = Parser.getTok().getIdentifier();1328Parser.Lex();1329if (parseEOL())1330return true;13311332MCSubtargetInfo &STI = copySTI();1333STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, "");1334setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));13351336getTargetStreamer().emitMachine(CPU);13371338return false;1339}13401341bool SystemZAsmParser::ParseGNUAttribute(SMLoc L) {1342int64_t Tag;1343int64_t IntegerValue;1344if (!Parser.parseGNUAttribute(L, Tag, IntegerValue))1345return Error(L, "malformed .gnu_attribute directive");13461347// Tag_GNU_S390_ABI_Vector tag is '8' and can be 0, 1, or 2.1348if (Tag != 8 || (IntegerValue < 0 || IntegerValue > 2))1349return Error(L, "unrecognized .gnu_attribute tag/value pair.");13501351Parser.getStreamer().emitGNUAttribute(Tag, IntegerValue);13521353return parseEOL();1354}13551356bool SystemZAsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,1357SMLoc &EndLoc, bool RestoreOnFailure) {1358Register Reg;1359if (parseRegister(Reg, RestoreOnFailure))1360return true;1361if (Reg.Group == RegGR)1362RegNo = SystemZMC::GR64Regs[Reg.Num];1363else if (Reg.Group == RegFP)1364RegNo = SystemZMC::FP64Regs[Reg.Num];1365else if (Reg.Group == RegV)1366RegNo = SystemZMC::VR128Regs[Reg.Num];1367else if (Reg.Group == RegAR)1368RegNo = SystemZMC::AR32Regs[Reg.Num];1369else if (Reg.Group == RegCR)1370RegNo = SystemZMC::CR64Regs[Reg.Num];1371StartLoc = Reg.StartLoc;1372EndLoc = Reg.EndLoc;1373return false;1374}13751376bool SystemZAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,1377SMLoc &EndLoc) {1378return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);1379}13801381ParseStatus SystemZAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,1382SMLoc &EndLoc) {1383bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);1384bool PendingErrors = getParser().hasPendingError();1385getParser().clearPendingErrors();1386if (PendingErrors)1387return ParseStatus::Failure;1388if (Result)1389return ParseStatus::NoMatch;1390return ParseStatus::Success;1391}13921393bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info,1394StringRef Name, SMLoc NameLoc,1395OperandVector &Operands) {13961397// Apply mnemonic aliases first, before doing anything else, in1398// case the target uses it.1399applyMnemonicAliases(Name, getAvailableFeatures(), getMAIAssemblerDialect());14001401Operands.push_back(SystemZOperand::createToken(Name, NameLoc));14021403// Read the remaining operands.1404if (getLexer().isNot(AsmToken::EndOfStatement)) {1405// Read the first operand.1406if (parseOperand(Operands, Name)) {1407return true;1408}14091410// Read any subsequent operands.1411while (getLexer().is(AsmToken::Comma)) {1412Parser.Lex();14131414if (isParsingHLASM() && getLexer().is(AsmToken::Space))1415return Error(1416Parser.getTok().getLoc(),1417"No space allowed between comma that separates operand entries");14181419if (parseOperand(Operands, Name)) {1420return true;1421}1422}14231424// Under the HLASM variant, we could have the remark field1425// The remark field occurs after the operation entries1426// There is a space that separates the operation entries and the1427// remark field.1428if (isParsingHLASM() && getTok().is(AsmToken::Space)) {1429// We've confirmed that there is a Remark field.1430StringRef Remark(getLexer().LexUntilEndOfStatement());1431Parser.Lex();14321433// If there is nothing after the space, then there is nothing to emit1434// We could have a situation as this:1435// " \n"1436// After lexing above, we will have1437// "\n"1438// This isn't an explicit remark field, so we don't have to output1439// this as a comment.1440if (Remark.size())1441// Output the entire Remarks Field as a comment1442getStreamer().AddComment(Remark);1443}14441445if (getLexer().isNot(AsmToken::EndOfStatement)) {1446SMLoc Loc = getLexer().getLoc();1447return Error(Loc, "unexpected token in argument list");1448}1449}14501451// Consume the EndOfStatement.1452Parser.Lex();1453return false;1454}14551456bool SystemZAsmParser::parseOperand(OperandVector &Operands,1457StringRef Mnemonic) {1458// Check if the current operand has a custom associated parser, if so, try to1459// custom parse the operand, or fallback to the general approach. Force all1460// features to be available during the operand check, or else we will fail to1461// find the custom parser, and then we will later get an InvalidOperand error1462// instead of a MissingFeature errror.1463FeatureBitset AvailableFeatures = getAvailableFeatures();1464FeatureBitset All;1465All.set();1466setAvailableFeatures(All);1467ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);1468setAvailableFeatures(AvailableFeatures);1469if (Res.isSuccess())1470return false;14711472// If there wasn't a custom match, try the generic matcher below. Otherwise,1473// there was a match, but an error occurred, in which case, just return that1474// the operand parsing failed.1475if (Res.isFailure())1476return true;14771478// Check for a register. All real register operands should have used1479// a context-dependent parse routine, which gives the required register1480// class. The code is here to mop up other cases, like those where1481// the instruction isn't recognized.1482if (isParsingATT() && Parser.getTok().is(AsmToken::Percent)) {1483Register Reg;1484if (parseRegister(Reg))1485return true;1486Operands.push_back(SystemZOperand::createInvalid(Reg.StartLoc, Reg.EndLoc));1487return false;1488}14891490// The only other type of operand is an immediate or address. As above,1491// real address operands should have used a context-dependent parse routine,1492// so we treat any plain expression as an immediate.1493SMLoc StartLoc = Parser.getTok().getLoc();1494Register Reg1, Reg2;1495bool HaveReg1, HaveReg2;1496const MCExpr *Expr;1497const MCExpr *Length;1498if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Expr, Length,1499/*HasLength*/ true, /*HasVectorIndex*/ true))1500return true;1501// If the register combination is not valid for any instruction, reject it.1502// Otherwise, fall back to reporting an unrecognized instruction.1503if (HaveReg1 && Reg1.Group != RegGR && Reg1.Group != RegV1504&& parseAddressRegister(Reg1))1505return true;1506if (HaveReg2 && parseAddressRegister(Reg2))1507return true;15081509SMLoc EndLoc =1510SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);1511if (HaveReg1 || HaveReg2 || Length)1512Operands.push_back(SystemZOperand::createInvalid(StartLoc, EndLoc));1513else1514Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));1515return false;1516}15171518bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,1519OperandVector &Operands,1520MCStreamer &Out,1521uint64_t &ErrorInfo,1522bool MatchingInlineAsm) {1523MCInst Inst;1524unsigned MatchResult;15251526unsigned Dialect = getMAIAssemblerDialect();15271528FeatureBitset MissingFeatures;1529MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,1530MatchingInlineAsm, Dialect);1531switch (MatchResult) {1532case Match_Success:1533Inst.setLoc(IDLoc);1534Out.emitInstruction(Inst, getSTI());1535return false;15361537case Match_MissingFeature: {1538assert(MissingFeatures.any() && "Unknown missing feature!");1539// Special case the error message for the very common case where only1540// a single subtarget feature is missing1541std::string Msg = "instruction requires:";1542for (unsigned I = 0, E = MissingFeatures.size(); I != E; ++I) {1543if (MissingFeatures[I]) {1544Msg += " ";1545Msg += getSubtargetFeatureName(I);1546}1547}1548return Error(IDLoc, Msg);1549}15501551case Match_InvalidOperand: {1552SMLoc ErrorLoc = IDLoc;1553if (ErrorInfo != ~0ULL) {1554if (ErrorInfo >= Operands.size())1555return Error(IDLoc, "too few operands for instruction");15561557ErrorLoc = ((SystemZOperand &)*Operands[ErrorInfo]).getStartLoc();1558if (ErrorLoc == SMLoc())1559ErrorLoc = IDLoc;1560}1561return Error(ErrorLoc, "invalid operand for instruction");1562}15631564case Match_MnemonicFail: {1565FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());1566std::string Suggestion = SystemZMnemonicSpellCheck(1567((SystemZOperand &)*Operands[0]).getToken(), FBS, Dialect);1568return Error(IDLoc, "invalid instruction" + Suggestion,1569((SystemZOperand &)*Operands[0]).getLocRange());1570}1571}15721573llvm_unreachable("Unexpected match type");1574}15751576ParseStatus SystemZAsmParser::parsePCRel(OperandVector &Operands,1577int64_t MinVal, int64_t MaxVal,1578bool AllowTLS) {1579MCContext &Ctx = getContext();1580MCStreamer &Out = getStreamer();1581const MCExpr *Expr;1582SMLoc StartLoc = Parser.getTok().getLoc();1583if (getParser().parseExpression(Expr))1584return ParseStatus::NoMatch;15851586auto IsOutOfRangeConstant = [&](const MCExpr *E, bool Negate) -> bool {1587if (auto *CE = dyn_cast<MCConstantExpr>(E)) {1588int64_t Value = CE->getValue();1589if (Negate)1590Value = -Value;1591if ((Value & 1) || Value < MinVal || Value > MaxVal)1592return true;1593}1594return false;1595};15961597// For consistency with the GNU assembler, treat immediates as offsets1598// from ".".1599if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {1600if (isParsingHLASM())1601return Error(StartLoc, "Expected PC-relative expression");1602if (IsOutOfRangeConstant(CE, false))1603return Error(StartLoc, "offset out of range");1604int64_t Value = CE->getValue();1605MCSymbol *Sym = Ctx.createTempSymbol();1606Out.emitLabel(Sym);1607const MCExpr *Base = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None,1608Ctx);1609Expr = Value == 0 ? Base : MCBinaryExpr::createAdd(Base, Expr, Ctx);1610}16111612// For consistency with the GNU assembler, conservatively assume that a1613// constant offset must by itself be within the given size range.1614if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr))1615if (IsOutOfRangeConstant(BE->getLHS(), false) ||1616IsOutOfRangeConstant(BE->getRHS(),1617BE->getOpcode() == MCBinaryExpr::Sub))1618return Error(StartLoc, "offset out of range");16191620// Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol.1621const MCExpr *Sym = nullptr;1622if (AllowTLS && getLexer().is(AsmToken::Colon)) {1623Parser.Lex();16241625if (Parser.getTok().isNot(AsmToken::Identifier))1626return Error(Parser.getTok().getLoc(), "unexpected token");16271628MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;1629StringRef Name = Parser.getTok().getString();1630if (Name == "tls_gdcall")1631Kind = MCSymbolRefExpr::VK_TLSGD;1632else if (Name == "tls_ldcall")1633Kind = MCSymbolRefExpr::VK_TLSLDM;1634else1635return Error(Parser.getTok().getLoc(), "unknown TLS tag");1636Parser.Lex();16371638if (Parser.getTok().isNot(AsmToken::Colon))1639return Error(Parser.getTok().getLoc(), "unexpected token");1640Parser.Lex();16411642if (Parser.getTok().isNot(AsmToken::Identifier))1643return Error(Parser.getTok().getLoc(), "unexpected token");16441645StringRef Identifier = Parser.getTok().getString();1646Sym = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(Identifier),1647Kind, Ctx);1648Parser.Lex();1649}16501651SMLoc EndLoc =1652SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);16531654if (AllowTLS)1655Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym,1656StartLoc, EndLoc));1657else1658Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc));16591660return ParseStatus::Success;1661}16621663bool SystemZAsmParser::isLabel(AsmToken &Token) {1664if (isParsingATT())1665return true;16661667// HLASM labels are ordinary symbols.1668// An HLASM label always starts at column 1.1669// An ordinary symbol syntax is laid out as follows:1670// Rules:1671// 1. Has to start with an "alphabetic character". Can be followed by up to1672// 62 alphanumeric characters. An "alphabetic character", in this scenario,1673// is a letter from 'A' through 'Z', or from 'a' through 'z',1674// or '$', '_', '#', or '@'1675// 2. Labels are case-insensitive. E.g. "lab123", "LAB123", "lAb123", etc.1676// are all treated as the same symbol. However, the processing for the case1677// folding will not be done in this function.1678StringRef RawLabel = Token.getString();1679SMLoc Loc = Token.getLoc();16801681// An HLASM label cannot be empty.1682if (!RawLabel.size())1683return !Error(Loc, "HLASM Label cannot be empty");16841685// An HLASM label cannot exceed greater than 63 characters.1686if (RawLabel.size() > 63)1687return !Error(Loc, "Maximum length for HLASM Label is 63 characters");16881689// A label must start with an "alphabetic character".1690if (!isHLASMAlpha(RawLabel[0]))1691return !Error(Loc, "HLASM Label has to start with an alphabetic "1692"character or the underscore character");16931694// Now, we've established that the length is valid1695// and the first character is alphabetic.1696// Check whether remaining string is alphanumeric.1697for (unsigned I = 1; I < RawLabel.size(); ++I)1698if (!isHLASMAlnum(RawLabel[I]))1699return !Error(Loc, "HLASM Label has to be alphanumeric");17001701return true;1702}17031704// Force static initialization.1705// NOLINTNEXTLINE(readability-identifier-naming)1706extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmParser() {1707RegisterMCAsmParser<SystemZAsmParser> X(getTheSystemZTarget());1708}170917101711