diff options
Diffstat (limited to 'contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 315 |
1 files changed, 232 insertions, 83 deletions
diff --git a/contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index cb528db..3aa4c6b 100644 --- a/contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/contrib/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -39,13 +39,17 @@ enum RegisterKind { ADDR64Reg, FP32Reg, FP64Reg, - FP128Reg + FP128Reg, + VR32Reg, + VR64Reg, + VR128Reg }; enum MemoryKind { BDMem, BDXMem, - BDLMem + BDLMem, + BDVMem }; class SystemZOperand : public MCParsedAsmOperand { @@ -57,6 +61,7 @@ private: KindReg, KindAccessReg, KindImm, + KindImmTLS, KindMem }; @@ -84,34 +89,42 @@ private: }; // Base + Disp + Index, where Base and Index are LLVM registers or 0. - // RegKind says what type the registers have (ADDR32Reg or ADDR64Reg). - // Length is the operand length for D(L,B)-style operands, otherwise - // it is null. + // MemKind says what type of memory this is and RegKind says what type + // the base register has (ADDR32Reg or ADDR64Reg). Length is the operand + // length for D(L,B)-style operands, otherwise it is null. struct MemOp { - unsigned Base : 8; - unsigned Index : 8; - unsigned RegKind : 8; - unsigned Unused : 8; + unsigned Base : 12; + unsigned Index : 12; + unsigned MemKind : 4; + unsigned RegKind : 4; const MCExpr *Disp; const MCExpr *Length; }; + // Imm is an immediate operand, and Sym is an optional TLS symbol + // for use with a __tls_get_offset marker relocation. + struct ImmTLSOp { + const MCExpr *Imm; + const MCExpr *Sym; + }; + union { TokenOp Token; RegOp Reg; unsigned AccessReg; const MCExpr *Imm; + ImmTLSOp ImmTLS; MemOp Mem; }; void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); else - Inst.addOperand(MCOperand::CreateExpr(Expr)); + Inst.addOperand(MCOperand::createExpr(Expr)); } public: @@ -149,10 +162,11 @@ public: return Op; } static std::unique_ptr<SystemZOperand> - createMem(RegisterKind RegKind, unsigned Base, const MCExpr *Disp, - unsigned Index, const MCExpr *Length, SMLoc StartLoc, - SMLoc EndLoc) { + createMem(MemoryKind MemKind, RegisterKind RegKind, unsigned Base, + const MCExpr *Disp, unsigned Index, const MCExpr *Length, + SMLoc StartLoc, SMLoc EndLoc) { auto Op = make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc); + Op->Mem.MemKind = MemKind; Op->Mem.RegKind = RegKind; Op->Mem.Base = Base; Op->Mem.Index = Index; @@ -160,6 +174,14 @@ public: Op->Mem.Length = Length; return Op; } + static std::unique_ptr<SystemZOperand> + createImmTLS(const MCExpr *Imm, const MCExpr *Sym, + SMLoc StartLoc, SMLoc EndLoc) { + auto Op = make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc); + Op->ImmTLS.Imm = Imm; + Op->ImmTLS.Sym = Sym; + return Op; + } // Token operands bool isToken() const override { @@ -200,24 +222,40 @@ public: return Imm; } + // Immediate operands with optional TLS symbol. + bool isImmTLS() const { + return Kind == KindImmTLS; + } + // Memory operands. bool isMem() const override { return Kind == KindMem; } - bool isMem(RegisterKind RegKind, MemoryKind MemKind) const { + bool isMem(MemoryKind MemKind) const { return (Kind == KindMem && - Mem.RegKind == RegKind && - (MemKind == BDXMem || !Mem.Index) && - (MemKind == BDLMem) == (Mem.Length != nullptr)); + (Mem.MemKind == MemKind || + // A BDMem can be treated as a BDXMem in which the index + // register field is 0. + (Mem.MemKind == BDMem && MemKind == BDXMem))); + } + bool isMem(MemoryKind MemKind, RegisterKind RegKind) const { + return isMem(MemKind) && Mem.RegKind == RegKind; } - bool isMemDisp12(RegisterKind RegKind, MemoryKind MemKind) const { - return isMem(RegKind, MemKind) && inRange(Mem.Disp, 0, 0xfff); + bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const { + return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff); } - bool isMemDisp20(RegisterKind RegKind, MemoryKind MemKind) const { - return isMem(RegKind, MemKind) && inRange(Mem.Disp, -524288, 524287); + bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const { + return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287); } bool isMemDisp12Len8(RegisterKind RegKind) const { - return isMemDisp12(RegKind, BDLMem) && inRange(Mem.Length, 1, 0x100); + return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length, 1, 0x100); + } + void addBDVAddrOperands(MCInst &Inst, unsigned N) const { + assert(N == 3 && "Invalid number of operands"); + assert(isMem(BDVMem) && "Invalid operand type"); + Inst.addOperand(MCOperand::createReg(Mem.Base)); + addExpr(Inst, Mem.Disp); + Inst.addOperand(MCOperand::createReg(Mem.Index)); } // Override MCParsedAsmOperand. @@ -229,12 +267,12 @@ public: // to an instruction. void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands"); - Inst.addOperand(MCOperand::CreateReg(getReg())); + Inst.addOperand(MCOperand::createReg(getReg())); } void addAccessRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands"); assert(Kind == KindAccessReg && "Invalid operand type"); - Inst.addOperand(MCOperand::CreateImm(AccessReg)); + Inst.addOperand(MCOperand::createImm(AccessReg)); } void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands"); @@ -242,24 +280,31 @@ public: } void addBDAddrOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands"); - assert(Kind == KindMem && Mem.Index == 0 && "Invalid operand type"); - Inst.addOperand(MCOperand::CreateReg(Mem.Base)); + assert(isMem(BDMem) && "Invalid operand type"); + Inst.addOperand(MCOperand::createReg(Mem.Base)); addExpr(Inst, Mem.Disp); } void addBDXAddrOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands"); - assert(Kind == KindMem && "Invalid operand type"); - Inst.addOperand(MCOperand::CreateReg(Mem.Base)); + assert(isMem(BDXMem) && "Invalid operand type"); + Inst.addOperand(MCOperand::createReg(Mem.Base)); addExpr(Inst, Mem.Disp); - Inst.addOperand(MCOperand::CreateReg(Mem.Index)); + Inst.addOperand(MCOperand::createReg(Mem.Index)); } void addBDLAddrOperands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands"); - assert(Kind == KindMem && "Invalid operand type"); - Inst.addOperand(MCOperand::CreateReg(Mem.Base)); + assert(isMem(BDLMem) && "Invalid operand type"); + Inst.addOperand(MCOperand::createReg(Mem.Base)); addExpr(Inst, Mem.Disp); addExpr(Inst, Mem.Length); } + void addImmTLSOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands"); + assert(Kind == KindImmTLS && "Invalid operand type"); + addExpr(Inst, ImmTLS.Imm); + if (ImmTLS.Sym) + addExpr(Inst, ImmTLS.Sym); + } // Used by the TableGen code to check for particular operand types. bool isGR32() const { return isReg(GR32Reg); } @@ -273,17 +318,26 @@ public: bool isFP32() const { return isReg(FP32Reg); } bool isFP64() const { return isReg(FP64Reg); } bool isFP128() const { return isReg(FP128Reg); } - bool isBDAddr32Disp12() const { return isMemDisp12(ADDR32Reg, BDMem); } - bool isBDAddr32Disp20() const { return isMemDisp20(ADDR32Reg, BDMem); } - bool isBDAddr64Disp12() const { return isMemDisp12(ADDR64Reg, BDMem); } - bool isBDAddr64Disp20() const { return isMemDisp20(ADDR64Reg, BDMem); } - bool isBDXAddr64Disp12() const { return isMemDisp12(ADDR64Reg, BDXMem); } - bool isBDXAddr64Disp20() const { return isMemDisp20(ADDR64Reg, BDXMem); } + bool isVR32() const { return isReg(VR32Reg); } + bool isVR64() const { return isReg(VR64Reg); } + bool isVF128() const { return false; } + bool isVR128() const { return isReg(VR128Reg); } + bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, ADDR32Reg); } + bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, ADDR32Reg); } + bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, ADDR64Reg); } + bool isBDAddr64Disp20() const { return isMemDisp20(BDMem, ADDR64Reg); } + bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, ADDR64Reg); } + bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, ADDR64Reg); } bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(ADDR64Reg); } + bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, ADDR64Reg); } + bool isU1Imm() const { return isImm(0, 1); } + bool isU2Imm() const { return isImm(0, 3); } + bool isU3Imm() const { return isImm(0, 7); } bool isU4Imm() const { return isImm(0, 15); } bool isU6Imm() const { return isImm(0, 63); } bool isU8Imm() const { return isImm(0, 255); } bool isS8Imm() const { return isImm(-128, 127); } + bool isU12Imm() const { return isImm(0, 4095); } bool isU16Imm() const { return isImm(0, 65535); } bool isS16Imm() const { return isImm(-32768, 32767); } bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); } @@ -300,6 +354,7 @@ private: enum RegisterGroup { RegGR, RegFP, + RegV, RegAccess }; struct Register { @@ -318,12 +373,15 @@ private: RegisterKind Kind); bool parseAddress(unsigned &Base, const MCExpr *&Disp, - unsigned &Index, const MCExpr *&Length, + unsigned &Index, bool &IsVector, const MCExpr *&Length, const unsigned *Regs, RegisterKind RegKind); OperandMatchResultTy parseAddress(OperandVector &Operands, - const unsigned *Regs, RegisterKind RegKind, - MemoryKind MemKind); + MemoryKind MemKind, const unsigned *Regs, + RegisterKind RegKind); + + OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal, + int64_t MaxVal, bool AllowTLS); bool parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -382,26 +440,45 @@ public: OperandMatchResultTy parseFP128(OperandVector &Operands) { return parseRegister(Operands, RegFP, SystemZMC::FP128Regs, FP128Reg); } + OperandMatchResultTy parseVR32(OperandVector &Operands) { + return parseRegister(Operands, RegV, SystemZMC::VR32Regs, VR32Reg); + } + OperandMatchResultTy parseVR64(OperandVector &Operands) { + return parseRegister(Operands, RegV, SystemZMC::VR64Regs, VR64Reg); + } + OperandMatchResultTy parseVF128(OperandVector &Operands) { + llvm_unreachable("Shouldn't be used as an operand"); + } + OperandMatchResultTy parseVR128(OperandVector &Operands) { + return parseRegister(Operands, RegV, SystemZMC::VR128Regs, VR128Reg); + } OperandMatchResultTy parseBDAddr32(OperandVector &Operands) { - return parseAddress(Operands, SystemZMC::GR32Regs, ADDR32Reg, BDMem); + return parseAddress(Operands, BDMem, SystemZMC::GR32Regs, ADDR32Reg); } OperandMatchResultTy parseBDAddr64(OperandVector &Operands) { - return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDMem); + return parseAddress(Operands, BDMem, SystemZMC::GR64Regs, ADDR64Reg); } OperandMatchResultTy parseBDXAddr64(OperandVector &Operands) { - return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDXMem); + return parseAddress(Operands, BDXMem, SystemZMC::GR64Regs, ADDR64Reg); } OperandMatchResultTy parseBDLAddr64(OperandVector &Operands) { - return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem); + return parseAddress(Operands, BDLMem, SystemZMC::GR64Regs, ADDR64Reg); + } + OperandMatchResultTy parseBDVAddr64(OperandVector &Operands) { + return parseAddress(Operands, BDVMem, SystemZMC::GR64Regs, ADDR64Reg); } OperandMatchResultTy parseAccessReg(OperandVector &Operands); - OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal, - int64_t MaxVal); OperandMatchResultTy parsePCRel16(OperandVector &Operands) { - return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1); + return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false); } OperandMatchResultTy parsePCRel32(OperandVector &Operands) { - return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1); + return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false); + } + OperandMatchResultTy parsePCRelTLS16(OperandVector &Operands) { + return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true); + } + OperandMatchResultTy parsePCRelTLS32(OperandVector &Operands) { + return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true); } }; } // end anonymous namespace @@ -443,6 +520,8 @@ bool SystemZAsmParser::parseRegister(Register &Reg) { Reg.Group = RegGR; else if (Prefix == 'f' && Reg.Num < 16) Reg.Group = RegFP; + else if (Prefix == 'v' && Reg.Num < 32) + Reg.Group = RegV; else if (Prefix == 'a' && Reg.Num < 16) Reg.Group = RegAccess; else @@ -493,8 +572,8 @@ SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterGroup Group, // Regs maps asm register numbers to LLVM register numbers and RegKind // says what kind of address register we're using (ADDR32Reg or ADDR64Reg). bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp, - unsigned &Index, const MCExpr *&Length, - const unsigned *Regs, + unsigned &Index, bool &IsVector, + const MCExpr *&Length, const unsigned *Regs, RegisterKind RegKind) { // Parse the displacement, which must always be present. if (getParser().parseExpression(Disp)) @@ -503,6 +582,7 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp, // Parse the optional base and index. Index = 0; Base = 0; + IsVector = false; Length = nullptr; if (getLexer().is(AsmToken::LParen)) { Parser.Lex(); @@ -510,12 +590,23 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp, if (getLexer().is(AsmToken::Percent)) { // Parse the first register and decide whether it's a base or an index. Register Reg; - if (parseRegister(Reg, RegGR, Regs, RegKind)) + if (parseRegister(Reg)) return true; - if (getLexer().is(AsmToken::Comma)) - Index = Reg.Num; - else - Base = Reg.Num; + if (Reg.Group == RegV) { + // A vector index register. The base register is optional. + IsVector = true; + Index = SystemZMC::VR128Regs[Reg.Num]; + } else if (Reg.Group == RegGR) { + if (Reg.Num == 0) + return Error(Reg.StartLoc, "%r0 used in an address"); + // If the are two registers, the first one is the index and the + // second is the base. + if (getLexer().is(AsmToken::Comma)) + Index = Regs[Reg.Num]; + else + Base = Regs[Reg.Num]; + } else + return Error(Reg.StartLoc, "invalid address register"); } else { // Parse the length. if (getParser().parseExpression(Length)) @@ -542,37 +633,46 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp, // Parse a memory operand and add it to Operands. The other arguments // are as above. SystemZAsmParser::OperandMatchResultTy -SystemZAsmParser::parseAddress(OperandVector &Operands, const unsigned *Regs, - RegisterKind RegKind, MemoryKind MemKind) { +SystemZAsmParser::parseAddress(OperandVector &Operands, MemoryKind MemKind, + const unsigned *Regs, RegisterKind RegKind) { SMLoc StartLoc = Parser.getTok().getLoc(); unsigned Base, Index; + bool IsVector; const MCExpr *Disp; const MCExpr *Length; - if (parseAddress(Base, Disp, Index, Length, Regs, RegKind)) + if (parseAddress(Base, Disp, Index, IsVector, Length, Regs, RegKind)) return MatchOperand_ParseFail; - if (Index && MemKind != BDXMem) - { - Error(StartLoc, "invalid use of indexed addressing"); - return MatchOperand_ParseFail; - } + if (IsVector && MemKind != BDVMem) { + Error(StartLoc, "invalid use of vector addressing"); + return MatchOperand_ParseFail; + } - if (Length && MemKind != BDLMem) - { - Error(StartLoc, "invalid use of length addressing"); - return MatchOperand_ParseFail; - } + if (!IsVector && MemKind == BDVMem) { + Error(StartLoc, "vector index required in address"); + return MatchOperand_ParseFail; + } - if (!Length && MemKind == BDLMem) - { - Error(StartLoc, "missing length in address"); - return MatchOperand_ParseFail; - } + if (Index && MemKind != BDXMem && MemKind != BDVMem) { + Error(StartLoc, "invalid use of indexed addressing"); + return MatchOperand_ParseFail; + } + + if (Length && MemKind != BDLMem) { + Error(StartLoc, "invalid use of length addressing"); + return MatchOperand_ParseFail; + } + + if (!Length && MemKind == BDLMem) { + Error(StartLoc, "missing length in address"); + return MatchOperand_ParseFail; + } SMLoc EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(SystemZOperand::createMem(RegKind, Base, Disp, Index, - Length, StartLoc, EndLoc)); + Operands.push_back(SystemZOperand::createMem(MemKind, RegKind, Base, Disp, + Index, Length, StartLoc, + EndLoc)); return MatchOperand_Success; } @@ -589,6 +689,8 @@ bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, RegNo = SystemZMC::GR64Regs[Reg.Num]; else if (Reg.Group == RegFP) RegNo = SystemZMC::FP64Regs[Reg.Num]; + else if (Reg.Group == RegV) + RegNo = SystemZMC::VR128Regs[Reg.Num]; else // FIXME: Access registers aren't modelled as LLVM registers yet. return Error(Reg.StartLoc, "invalid operand for instruction"); @@ -661,8 +763,10 @@ bool SystemZAsmParser::parseOperand(OperandVector &Operands, // so we treat any plain expression as an immediate. SMLoc StartLoc = Parser.getTok().getLoc(); unsigned Base, Index; + bool IsVector; const MCExpr *Expr, *Length; - if (parseAddress(Base, Expr, Index, Length, SystemZMC::GR64Regs, ADDR64Reg)) + if (parseAddress(Base, Expr, Index, IsVector, Length, SystemZMC::GR64Regs, + ADDR64Reg)) return true; SMLoc EndLoc = @@ -743,7 +847,7 @@ SystemZAsmParser::parseAccessReg(OperandVector &Operands) { SystemZAsmParser::OperandMatchResultTy SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal, - int64_t MaxVal) { + int64_t MaxVal, bool AllowTLS) { MCContext &Ctx = getContext(); MCStreamer &Out = getStreamer(); const MCExpr *Expr; @@ -759,16 +863,61 @@ SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal, Error(StartLoc, "offset out of range"); return MatchOperand_ParseFail; } - MCSymbol *Sym = Ctx.CreateTempSymbol(); + MCSymbol *Sym = Ctx.createTempSymbol(); Out.EmitLabel(Sym); - const MCExpr *Base = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + const MCExpr *Base = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); - Expr = Value == 0 ? Base : MCBinaryExpr::CreateAdd(Base, Expr, Ctx); + Expr = Value == 0 ? Base : MCBinaryExpr::createAdd(Base, Expr, Ctx); + } + + // Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol. + const MCExpr *Sym = nullptr; + if (AllowTLS && getLexer().is(AsmToken::Colon)) { + Parser.Lex(); + + if (Parser.getTok().isNot(AsmToken::Identifier)) { + Error(Parser.getTok().getLoc(), "unexpected token"); + return MatchOperand_ParseFail; + } + + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; + StringRef Name = Parser.getTok().getString(); + if (Name == "tls_gdcall") + Kind = MCSymbolRefExpr::VK_TLSGD; + else if (Name == "tls_ldcall") + Kind = MCSymbolRefExpr::VK_TLSLDM; + else { + Error(Parser.getTok().getLoc(), "unknown TLS tag"); + return MatchOperand_ParseFail; + } + Parser.Lex(); + + if (Parser.getTok().isNot(AsmToken::Colon)) { + Error(Parser.getTok().getLoc(), "unexpected token"); + return MatchOperand_ParseFail; + } + Parser.Lex(); + + if (Parser.getTok().isNot(AsmToken::Identifier)) { + Error(Parser.getTok().getLoc(), "unexpected token"); + return MatchOperand_ParseFail; + } + + StringRef Identifier = Parser.getTok().getString(); + Sym = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(Identifier), + Kind, Ctx); + Parser.Lex(); } SMLoc EndLoc = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); + + if (AllowTLS) + Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym, + StartLoc, EndLoc)); + else + Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); + return MatchOperand_Success; } |