[AMDGPU][MC] Corrected handling of "-" before expressions

See bug 41156: https://bugs.llvm.org/show_bug.cgi?id=41156

Reviewers: artem.tamazov, arsenm

Differential Revision: https://reviews.llvm.org/D60622

llvm-svn: 358596
This commit is contained in:
Dmitry Preobrazhensky 2019-04-17 16:56:34 +00:00
parent dc9e7dcbb0
commit 394d0a1637
2 changed files with 76 additions and 41 deletions

View File

@ -1079,8 +1079,8 @@ public:
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 @@ private:
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 @@ std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
}
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;
}
if (Negate)
RealVal.changeSign();
Operands.push_back(
AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S,
AMDGPUOperand::ImmTyNone, true));
return MatchOperand_Success;
// 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, HasSP3AbsModifier))
return MatchOperand_ParseFail;
Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
return MatchOperand_Success;
}
case AsmToken::Real: {
int64_t IntVal;
if (parseAbsoluteExpr(IntVal, AbsMod))
return MatchOperand_ParseFail;
APFloat F(BitsToDouble(IntVal));
if (Minus)
F.changeSign();
Operands.push_back(
AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
AMDGPUOperand::ImmTyNone, true));
return MatchOperand_Success;
}
default:
return MatchOperand_NoMatch;
}
return MatchOperand_NoMatch;
}
OperandMatchResultTy
@ -4632,6 +4647,11 @@ AMDGPUAsmParser::getLoc() const {
return getToken().getLoc();
}
StringRef
AMDGPUAsmParser::getTokenStr() const {
return getToken().getString();
}
void
AMDGPUAsmParser::lex() {
Parser.Lex();

View File

@ -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 @@ s_sub_u32 s0, s0, -t
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