Index: llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ llvm/trunk/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1080,6 +1080,7 @@ StringRef &Value); bool parseAbsoluteExpr(int64_t &Val, bool HasSP3AbsModifier = false); + bool parseSP3NegModifier(); OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false); OperandMatchResultTy parseReg(OperandVector &Operands); OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false); @@ -1134,6 +1135,7 @@ bool trySkipToken(const AsmToken::TokenKind Kind); bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg); bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string"); + void peekTokens(MutableArrayRef Tokens); AsmToken::TokenKind getTokenKind() const; bool parseExpr(int64_t &Imm); StringRef getTokenStr() const; @@ -2104,34 +2106,58 @@ res; } +// Check if the current token is an SP3 'neg' modifier. +// Currently this modifier is allowed in the following context: +// +// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]". +// 2. Before an 'abs' modifier: -abs(...) +// 3. Before an SP3 'abs' modifier: -|...| +// +// In all other cases "-" is handled as a part +// of an expression that follows the sign. +// +// Note: When "-" is followed by an integer literal, +// this is interpreted as integer negation rather +// than a floating-point NEG modifier applied to N. +// Beside being contr-intuitive, such use of floating-point +// NEG modifier would have resulted in different meaning +// of integer literals used with VOP1/2/C and VOP3, +// for example: +// v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF +// v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001 +// Negative fp literals with preceding "-" are +// handled likewise for unifomtity +// +bool +AMDGPUAsmParser::parseSP3NegModifier() { + + AsmToken NextToken[2]; + peekTokens(NextToken); + + if (isToken(AsmToken::Minus) && + (isRegister(NextToken[0], NextToken[1]) || + NextToken[0].is(AsmToken::Pipe) || + isId(NextToken[0], "abs"))) { + lex(); + return true; + } + + return false; +} + OperandMatchResultTy AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm) { - bool Negate = false, Negate2 = false, Abs = false, Abs2 = false; + bool Negate, Negate2 = false, Abs = false, Abs2 = false; - if (getLexer().getKind()== AsmToken::Minus) { - const AsmToken NextToken = getLexer().peekTok(); - - // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead. - if (NextToken.is(AsmToken::Minus)) { - Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier"); - return MatchOperand_ParseFail; - } - - // '-' followed by an integer literal N should be interpreted as integer - // negation rather than a floating-point NEG modifier applied to N. - // Beside being contr-intuitive, such use of floating-point NEG modifier - // results in different meaning of integer literals used with VOP1/2/C - // and VOP3, for example: - // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF - // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001 - // Negative fp literals should be handled likewise for unifomtity - if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) { - Parser.Lex(); - Negate = true; - } + // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead. + if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) { + Error(getLoc(), "invalid syntax, expected 'neg' modifier"); + return MatchOperand_ParseFail; } + Negate = parseSP3NegModifier(); + if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "neg") { if (Negate) { @@ -2174,7 +2200,7 @@ Res = parseReg(Operands); } if (Res != MatchOperand_Success) { - return Res; + return (Negate || Negate2 || Abs || Abs2)? MatchOperand_ParseFail : Res; } AMDGPUOperand::Modifiers Mods; @@ -2236,7 +2262,7 @@ Res = parseReg(Operands); } if (Res != MatchOperand_Success) { - return Res; + return Sext? MatchOperand_ParseFail : Res; } AMDGPUOperand::Modifiers Mods; @@ -4637,6 +4663,14 @@ return getLexer().peekTok(); } +void +AMDGPUAsmParser::peekTokens(MutableArrayRef Tokens) { + auto TokCount = getLexer().peekTokens(Tokens); + + for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx) + Tokens[Idx] = AsmToken(AsmToken::Error, ""); +} + AsmToken::TokenKind AMDGPUAsmParser::getTokenKind() const { return getLexer().getKind(); Index: llvm/trunk/test/MC/AMDGPU/expressions.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/expressions.s +++ llvm/trunk/test/MC/AMDGPU/expressions.s @@ -72,3 +72,31 @@ t=10000000000 s_sub_u32 s0, s0, 1.0 + t // NOVI: error: invalid operand for instruction + +//===----------------------------------------------------------------------===// +// Symbols may look like registers. +// They should be allowed in expressions if there is no ambiguity. +//===----------------------------------------------------------------------===// + +v=1 +v_sin_f32 v0, -v +// VI: v_sin_f32_e32 v0, -1 ; encoding: [0xc1,0x52,0x00,0x7e] + +v_sin_f32 v0, -v[0] +// VI: v_sin_f32_e64 v0, -v0 ; encoding: [0x00,0x00,0x69,0xd1,0x00,0x01,0x00,0x20] + +s=1 +v_sin_f32 v0, -s +// VI: v_sin_f32_e32 v0, -1 ; encoding: [0xc1,0x52,0x00,0x7e] + +s0=1 +v_sin_f32 v0, -s0 +// VI: v_sin_f32_e64 v0, -s0 ; encoding: [0x00,0x00,0x69,0xd1,0x00,0x00,0x00,0x20] + +ttmp=1 +v_sin_f32 v0, -ttmp +// VI: v_sin_f32_e32 v0, -1 ; encoding: [0xc1,0x52,0x00,0x7e] + +ttmp0=1 +v_sin_f32 v0, -[ttmp0] +// VI: v_sin_f32_e64 v0, -ttmp0 ; encoding: [0x00,0x00,0x69,0xd1,0x70,0x00,0x00,0x20] Index: llvm/trunk/test/MC/AMDGPU/vop3-modifiers-err.s =================================================================== --- llvm/trunk/test/MC/AMDGPU/vop3-modifiers-err.s +++ llvm/trunk/test/MC/AMDGPU/vop3-modifiers-err.s @@ -12,4 +12,4 @@ // CHECK: error: invalid syntax, expected 'neg' modifier v_ceil_f16 v0, abs(neg(1)) -// CHECK: error: not a valid operand \ No newline at end of file +// CHECK: error: failed parsing operand