diff options
Diffstat (limited to 'contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 199 |
1 files changed, 147 insertions, 52 deletions
diff --git a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index d743aa6..e896571 100644 --- a/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/contrib/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -11,6 +11,7 @@ #include "X86AsmInstrumentation.h" #include "X86AsmParserCommon.h" #include "X86Operand.h" +#include "X86ISelLowering.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" @@ -664,6 +665,7 @@ private: ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size); std::unique_ptr<X86Operand> ParseIntelMemOperand(int64_t ImmDisp, SMLoc StartLoc, unsigned Size); + std::unique_ptr<X86Operand> ParseRoundingModeOp(SMLoc Start, SMLoc End); bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); std::unique_ptr<X86Operand> ParseIntelBracExpression(unsigned SegReg, SMLoc Start, @@ -727,23 +729,24 @@ private: bool is64BitMode() const { // FIXME: Can tablegen auto-generate this? - return (STI.getFeatureBits() & X86::Mode64Bit) != 0; + return STI.getFeatureBits()[X86::Mode64Bit]; } bool is32BitMode() const { // FIXME: Can tablegen auto-generate this? - return (STI.getFeatureBits() & X86::Mode32Bit) != 0; + return STI.getFeatureBits()[X86::Mode32Bit]; } bool is16BitMode() const { // FIXME: Can tablegen auto-generate this? - return (STI.getFeatureBits() & X86::Mode16Bit) != 0; + return STI.getFeatureBits()[X86::Mode16Bit]; } - void SwitchMode(uint64_t mode) { - uint64_t oldMode = STI.getFeatureBits() & - (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit); - unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(oldMode | mode)); + void SwitchMode(unsigned mode) { + FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit}); + FeatureBitset OldMode = STI.getFeatureBits() & AllModes; + unsigned FB = ComputeAvailableFeatures( + STI.ToggleFeature(OldMode.flip(mode))); setAvailableFeatures(FB); - assert(mode == (STI.getFeatureBits() & - (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit))); + + assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes)); } unsigned getPointerWidth() { @@ -970,7 +973,7 @@ void X86AsmParser::SetFrameRegister(unsigned RegNo) { std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { unsigned basereg = is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI); - const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); + const MCExpr *Disp = MCConstantExpr::create(0, getContext()); return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0); @@ -979,7 +982,7 @@ std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) { unsigned basereg = is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI); - const MCExpr *Disp = MCConstantExpr::Create(0, getContext()); + const MCExpr *Disp = MCConstantExpr::create(0, getContext()); return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp, /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0); @@ -1189,10 +1192,10 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { StringRef IDVal = getTok().getString(); if (IDVal == "f" || IDVal == "b") { MCSymbol *Sym = - getContext().GetDirectionalLocalSymbol(IntVal, IDVal == "b"); + getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b"); MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; const MCExpr *Val = - MCSymbolRefExpr::Create(Sym, Variant, getContext()); + MCSymbolRefExpr::create(Sym, Variant, getContext()); if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); StringRef Identifier = Sym->getName(); @@ -1262,9 +1265,9 @@ X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, } if (SM.getImm() || !Disp) { - const MCExpr *Imm = MCConstantExpr::Create(SM.getImm(), getContext()); + const MCExpr *Imm = MCConstantExpr::create(SM.getImm(), getContext()); if (Disp) - Disp = MCBinaryExpr::CreateAdd(Disp, Imm, getContext()); + Disp = MCBinaryExpr::createAdd(Disp, Imm, getContext()); else Disp = Imm; // An immediate displacement only. } @@ -1349,9 +1352,9 @@ bool X86AsmParser::ParseIntelIdentifier(const MCExpr *&Val, } // Create the symbol reference. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier); + MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - Val = MCSymbolRefExpr::Create(Sym, Variant, getParser().getContext()); + Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext()); return false; } @@ -1379,7 +1382,7 @@ X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, // An immediate following a 'segment register', 'colon' token sequence can // be followed by a bracketed expression. If it isn't we know we have our // final segment override. - const MCExpr *Disp = MCConstantExpr::Create(ImmDisp, getContext()); + const MCExpr *Disp = MCConstantExpr::create(ImmDisp, getContext()); return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, /*BaseReg=*/0, /*IndexReg=*/0, /*Scale=*/1, Start, ImmDispToken.getEndLoc(), Size); @@ -1407,6 +1410,43 @@ X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, /*Scale=*/1, Start, End, Size, Identifier, Info); } +//ParseRoundingModeOp - Parse AVX-512 rounding mode operand +std::unique_ptr<X86Operand> +X86AsmParser::ParseRoundingModeOp(SMLoc Start, SMLoc End) { + MCAsmParser &Parser = getParser(); + const AsmToken &Tok = Parser.getTok(); + // Eat "{" and mark the current place. + const SMLoc consumedToken = consumeToken(); + if (Tok.getIdentifier().startswith("r")){ + int rndMode = StringSwitch<int>(Tok.getIdentifier()) + .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT) + .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF) + .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF) + .Case("rz", X86::STATIC_ROUNDING::TO_ZERO) + .Default(-1); + if (-1 == rndMode) + return ErrorOperand(Tok.getLoc(), "Invalid rounding mode."); + Parser.Lex(); // Eat "r*" of r*-sae + if (!getLexer().is(AsmToken::Minus)) + return ErrorOperand(Tok.getLoc(), "Expected - at this point"); + Parser.Lex(); // Eat "-" + Parser.Lex(); // Eat the sae + if (!getLexer().is(AsmToken::RCurly)) + return ErrorOperand(Tok.getLoc(), "Expected } at this point"); + Parser.Lex(); // Eat "}" + const MCExpr *RndModeOp = + MCConstantExpr::create(rndMode, Parser.getContext()); + return X86Operand::CreateImm(RndModeOp, Start, End); + } + if(Tok.getIdentifier().equals("sae")){ + Parser.Lex(); // Eat the sae + if (!getLexer().is(AsmToken::RCurly)) + return ErrorOperand(Tok.getLoc(), "Expected } at this point"); + Parser.Lex(); // Eat "}" + return X86Operand::CreateToken("{sae}", consumedToken); + } + return ErrorOperand(Tok.getLoc(), "unknown token in expression"); +} /// ParseIntelMemOperand - Parse intel style memory operand. std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, SMLoc Start, @@ -1459,7 +1499,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, return nullptr; } - const MCExpr *Disp = MCConstantExpr::Create(SM.getImm(), getContext()); + const MCExpr *Disp = MCConstantExpr::create(SM.getImm(), getContext()); // BaseReg is non-zero to avoid assertions. In the context of inline asm, // we're pointing to a local variable in memory, so the base register is // really the frame or stack pointer. @@ -1509,7 +1549,7 @@ bool X86AsmParser::ParseIntelDotOperator(const MCExpr *Disp, Val)); } - NewDisp = MCConstantExpr::Create(OrigDispVal + DotDispVal, getContext()); + NewDisp = MCConstantExpr::create(OrigDispVal + DotDispVal, getContext()); return false; } @@ -1583,7 +1623,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) { unsigned Len = End.getPointer() - TypeLoc.getPointer(); InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, CVal)); - const MCExpr *Imm = MCConstantExpr::Create(CVal, getContext()); + const MCExpr *Imm = MCConstantExpr::create(CVal, getContext()); return X86Operand::CreateImm(Imm, Start, End); } @@ -1643,7 +1683,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() { return X86Operand::CreateMem(getPointerWidth(), SM.getSym(), Start, End, Size); - const MCExpr *ImmExpr = MCConstantExpr::Create(Imm, getContext()); + const MCExpr *ImmExpr = MCConstantExpr::create(Imm, getContext()); return X86Operand::CreateImm(ImmExpr, Start, End); } @@ -1656,6 +1696,11 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() { return ParseIntelMemOperand(Imm, Start, Size); } + // rounding mode token + if (STI.getFeatureBits()[X86::FeatureAVX512] && + getLexer().is(AsmToken::LCurly)) + return ParseRoundingModeOp(Start, End); + // Register. unsigned RegNo = 0; if (!ParseRegister(RegNo, Start, End)) { @@ -1708,13 +1753,19 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() { return nullptr; return X86Operand::CreateImm(Val, Start, End); } + case AsmToken::LCurly:{ + SMLoc Start = Parser.getTok().getLoc(), End; + if (STI.getFeatureBits()[X86::FeatureAVX512]) + return ParseRoundingModeOp(Start, End); + return ErrorOperand(Start, "unknown token in expression"); + } } } bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands, const MCParsedAsmOperand &Op) { MCAsmParser &Parser = getParser(); - if(STI.getFeatureBits() & X86::FeatureAVX512) { + if(STI.getFeatureBits()[X86::FeatureAVX512]) { if (getLexer().is(AsmToken::LCurly)) { // Eat "{" and mark the current place. const SMLoc consumedToken = consumeToken(); @@ -1790,7 +1841,7 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg, // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The // only way to do this without lookahead is to eat the '(' and see what is // after it. - const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); + const MCExpr *Disp = MCConstantExpr::create(0, getParser().getContext()); if (getLexer().isNot(AsmToken::LParen)) { SMLoc ExprEnd; if (getParser().parseExpression(Disp, ExprEnd)) return nullptr; @@ -1964,14 +2015,13 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, PatchedName = PatchedName.substr(0, Name.size()-1); // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}. - const MCExpr *ExtraImmOp = nullptr; if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) && (PatchedName.endswith("ss") || PatchedName.endswith("sd") || PatchedName.endswith("ps") || PatchedName.endswith("pd"))) { bool IsVCMP = PatchedName[0] == 'v'; - unsigned SSECCIdx = IsVCMP ? 4 : 3; - unsigned SSEComparisonCode = StringSwitch<unsigned>( - PatchedName.slice(SSECCIdx, PatchedName.size() - 2)) + unsigned CCIdx = IsVCMP ? 4 : 3; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(CCIdx, PatchedName.size() - 2)) .Case("eq", 0x00) .Case("lt", 0x01) .Case("le", 0x02) @@ -2006,27 +2056,75 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, .Case("gt_oq", 0x1E) .Case("true_us", 0x1F) .Default(~0U); - if (SSEComparisonCode != ~0U && (IsVCMP || SSEComparisonCode < 8)) { - ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode, - getParser().getContext()); - if (PatchedName.endswith("ss")) { - PatchedName = IsVCMP ? "vcmpss" : "cmpss"; - } else if (PatchedName.endswith("sd")) { - PatchedName = IsVCMP ? "vcmpsd" : "cmpsd"; - } else if (PatchedName.endswith("ps")) { - PatchedName = IsVCMP ? "vcmpps" : "cmpps"; - } else { - assert(PatchedName.endswith("pd") && "Unexpected mnemonic!"); - PatchedName = IsVCMP ? "vcmppd" : "cmppd"; - } + if (ComparisonCode != ~0U && (IsVCMP || ComparisonCode < 8)) { + + Operands.push_back(X86Operand::CreateToken(PatchedName.slice(0, CCIdx), + NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - 2); + } + } + + // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}. + if (PatchedName.startswith("vpcmp") && + (PatchedName.endswith("b") || PatchedName.endswith("w") || + PatchedName.endswith("d") || PatchedName.endswith("q"))) { + unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(5, PatchedName.size() - CCIdx)) + .Case("eq", 0x0) // Only allowed on unsigned. Checked below. + .Case("lt", 0x1) + .Case("le", 0x2) + //.Case("false", 0x3) // Not a documented alias. + .Case("neq", 0x4) + .Case("nlt", 0x5) + .Case("nle", 0x6) + //.Case("true", 0x7) // Not a documented alias. + .Default(~0U); + if (ComparisonCode != ~0U && (ComparisonCode != 0 || CCIdx == 2)) { + Operands.push_back(X86Operand::CreateToken("vpcmp", NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - CCIdx); + } + } + + // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}. + if (PatchedName.startswith("vpcom") && + (PatchedName.endswith("b") || PatchedName.endswith("w") || + PatchedName.endswith("d") || PatchedName.endswith("q"))) { + unsigned CCIdx = PatchedName.drop_back().back() == 'u' ? 2 : 1; + unsigned ComparisonCode = StringSwitch<unsigned>( + PatchedName.slice(5, PatchedName.size() - CCIdx)) + .Case("lt", 0x0) + .Case("le", 0x1) + .Case("gt", 0x2) + .Case("ge", 0x3) + .Case("eq", 0x4) + .Case("neq", 0x5) + .Case("false", 0x6) + .Case("true", 0x7) + .Default(~0U); + if (ComparisonCode != ~0U) { + Operands.push_back(X86Operand::CreateToken("vpcom", NameLoc)); + + const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode, + getParser().getContext()); + Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); + + PatchedName = PatchedName.substr(PatchedName.size() - CCIdx); } } Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); - if (ExtraImmOp && !isParsingIntelSyntax()) - Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); - // Determine whether this is an instruction prefix. bool isPrefix = Name == "lock" || Name == "rep" || @@ -2072,9 +2170,6 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, (isPrefix && getLexer().is(AsmToken::Slash))) Parser.Lex(); - if (ExtraImmOp && isParsingIntelSyntax()) - Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); - // This is a terrible hack to handle "out[bwl]? %al, (%dx)" -> // "outb %al, %dx". Out doesn't take a memory form, but this is a widely // documented form in various unofficial manuals, so a lot of code uses it. @@ -2239,8 +2334,8 @@ static bool convertToSExti8(MCInst &Inst, unsigned Opcode, unsigned Reg, MCInst TmpInst; TmpInst.setOpcode(Opcode); if (!isCmp) - TmpInst.addOperand(MCOperand::CreateReg(Reg)); - TmpInst.addOperand(MCOperand::CreateReg(Reg)); + TmpInst.addOperand(MCOperand::createReg(Reg)); + TmpInst.addOperand(MCOperand::createReg(Reg)); TmpInst.addOperand(Inst.getOperand(0)); Inst = TmpInst; return true; @@ -2280,7 +2375,7 @@ bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) { X86Operand &Op = static_cast<X86Operand &>(*Ops[1]); assert(Op.isImm() && "expected immediate"); int64_t Res; - if (!Op.getImm()->EvaluateAsAbsolute(Res) || Res > 255) { + if (!Op.getImm()->evaluateAsAbsolute(Res) || Res > 255) { Error(Op.getStartLoc(), "interrupt vector must be in range [0-255]"); return false; } @@ -2485,7 +2580,7 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, SmallString<16> Tmp; Tmp += Base; Tmp += ' '; - Op.setTokenValue(Tmp.str()); + Op.setTokenValue(Tmp); // If this instruction starts with an 'f', then it is a floating point stack // instruction. These come in up to three forms for 32-bit, 64-bit, and @@ -2668,7 +2763,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, } // If we haven't matched anything yet, this is not a basic integer or FPU - // operation. There shouldn't be any ambiguity in our mneumonic table, so try + // operation. There shouldn't be any ambiguity in our mnemonic table, so try // matching with the unsized operand. if (Match.empty()) { Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo, |