Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -1079,8 +1079,8 @@ OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, StringRef &Value); - bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false); - OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false); + bool parseAbsoluteExpr(int64_t &Val, bool HasSP3AbsModifier = false); + OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false); OperandMatchResultTy parseReg(OperandVector &Operands); OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false); OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true); @@ -1136,6 +1136,7 @@ bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string"); AsmToken::TokenKind getTokenKind() const; bool parseExpr(int64_t &Imm); + StringRef getTokenStr() const; AsmToken peekToken(); AsmToken getToken() const; SMLoc getLoc() const; @@ -2001,70 +2002,84 @@ } bool -AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) { - if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) && - (getLexer().getKind() == AsmToken::Integer || - getLexer().getKind() == AsmToken::Real)) { - // This is a workaround for handling operands like these: +AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool HasSP3AbsModifier) { + if (HasSP3AbsModifier) { + // This is a workaround for handling expressions + // as arguments of SP3 'abs' modifier, for example: // |1.0| // |-1| + // |1+x| // This syntax is not compatible with syntax of standard // MC expressions (due to the trailing '|'). SMLoc EndLoc; const MCExpr *Expr; + SMLoc StartLoc = getLoc(); if (getParser().parsePrimaryExpr(Expr, EndLoc)) { return true; } - return !Expr->evaluateAsAbsolute(Val); + if (!Expr->evaluateAsAbsolute(Val)) + return Error(StartLoc, "expected absolute expression"); + + return false; } return getParser().parseAbsoluteExpression(Val); } OperandMatchResultTy -AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) { +AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) { // TODO: add syntactic sugar for 1/(2*PI) - bool Minus = false; - if (getLexer().getKind() == AsmToken::Minus) { - const AsmToken NextToken = getLexer().peekTok(); - if (!NextToken.is(AsmToken::Integer) && - !NextToken.is(AsmToken::Real)) { - return MatchOperand_NoMatch; - } - Minus = true; - Parser.Lex(); + + const auto& Tok = getToken(); + const auto& NextTok = peekToken(); + bool IsReal = Tok.is(AsmToken::Real); + SMLoc S = Tok.getLoc(); + bool Negate = false; + + if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) { + lex(); + IsReal = true; + Negate = true; } - SMLoc S = Parser.getTok().getLoc(); - switch(getLexer().getKind()) { - case AsmToken::Integer: { - int64_t IntVal; - if (parseAbsoluteExpr(IntVal, AbsMod)) + if (IsReal) { + // Floating-point expressions are not supported. + // Can only allow floating-point literals with an + // optional sign. + + StringRef Num = getTokenStr(); + lex(); + + APFloat RealVal(APFloat::IEEEdouble()); + auto roundMode = APFloat::rmNearestTiesToEven; + if (RealVal.convertFromString(Num, roundMode) == APFloat::opInvalidOp) { return MatchOperand_ParseFail; - if (Minus) - IntVal *= -1; - Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); + } + if (Negate) + RealVal.changeSign(); + + Operands.push_back( + AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S, + AMDGPUOperand::ImmTyNone, true)); + return MatchOperand_Success; - } - case AsmToken::Real: { + + // FIXME: Should enable arbitrary expressions here + } else if (Tok.is(AsmToken::Integer) || + (Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Integer))){ + int64_t IntVal; - if (parseAbsoluteExpr(IntVal, AbsMod)) + if (parseAbsoluteExpr(IntVal, HasSP3AbsModifier)) return MatchOperand_ParseFail; - APFloat F(BitsToDouble(IntVal)); - if (Minus) - F.changeSign(); - Operands.push_back( - AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S, - AMDGPUOperand::ImmTyNone, true)); + Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); return MatchOperand_Success; } - default: - return MatchOperand_NoMatch; - } + + return MatchOperand_NoMatch; } OperandMatchResultTy @@ -4632,6 +4647,11 @@ return getToken().getLoc(); } +StringRef +AMDGPUAsmParser::getTokenStr() const { + return getToken().getString(); +} + void AMDGPUAsmParser::lex() { Parser.Lex(); Index: test/MC/AMDGPU/expressions.s =================================================================== --- test/MC/AMDGPU/expressions.s +++ test/MC/AMDGPU/expressions.s @@ -1,4 +1,5 @@ -// RUN: llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s | FileCheck %s --check-prefix=VI +// RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s | FileCheck %s --check-prefix=VI +// RUN: not llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s 2>&1 | FileCheck %s --check-prefix=NOVI .globl global @@ -57,3 +58,17 @@ t=-1 s_sub_u32 s0, s0, -t // VI: s_sub_u32 s0, s0, 1 ; encoding: [0x00,0x81,0x80,0x80] + +s_sub_u32 s0, s0, -2+1 +// VI: s_sub_u32 s0, s0, -1 ; encoding: [0x00,0xc1,0x80,0x80] + +t=1 +s_sub_u32 s0, s0, -2+t +// VI: s_sub_u32 s0, s0, -1 ; encoding: [0x00,0xc1,0x80,0x80] + +s_sub_u32 s0, s0, -1.0 + 10000000000 +// NOVI: error: invalid operand for instruction + +t=10000000000 +s_sub_u32 s0, s0, 1.0 + t +// NOVI: error: invalid operand for instruction