AMDGPU/AsmParser: Add support for parsing symbol operands

Summary:
We can now reference symbols directly in operands, like this:
s_mov_b32 s0, global

Reviewers: artem.tamazov, vpykhtin, SamWot, nhaustov

Subscribers: arsenm, llvm-commits, kzhuravl

Differential Revision: http://reviews.llvm.org/D21038

llvm-svn: 272748
This commit is contained in:
Tom Stellard 2016-06-15 02:54:14 +00:00
parent 996b690cdd
commit f545457356
2 changed files with 77 additions and 2 deletions

View File

@ -158,7 +158,17 @@ public:
};
bool isToken() const override {
return Kind == Token;
if (Kind == Token)
return true;
if (Kind != Expression || !Expr)
return false;
// When parsing operands, we can't always tell if something was meant to be
// a token, like 'gds', or an expression that references a global variable.
// In this case, we assume the string is an expression, and if we need to
// interpret is a token, then we treat the symbol name as the token.
return isa<MCSymbolRefExpr>(Expr);
}
bool isImm() const override {
@ -246,7 +256,7 @@ public:
}
bool isSSrc32() const {
return isImm() || isSCSrc32();
return isImm() || isSCSrc32() || isExpr();
}
bool isSSrc64() const {
@ -296,7 +306,19 @@ public:
bool isSMRDLiteralOffset() const;
bool isDPPCtrl() const;
StringRef getExpressionAsToken() const {
assert(isExpr());
const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
return S->getSymbol().getName();
}
StringRef getToken() const {
assert(isToken());
if (Kind == Expression)
return getExpressionAsToken();
return StringRef(Tok.Data, Tok.Length);
}
@ -374,6 +396,8 @@ public:
void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
if (isRegKind())
addRegOperands(Inst, N);
else if (isExpr())
Inst.addOperand(MCOperand::createExpr(Expr));
else
addImmOperands(Inst, N);
}
@ -1448,7 +1472,19 @@ AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
return ResTy;
if (getLexer().getKind() == AsmToken::Identifier) {
// If this identifier is a symbol, we want to create an expression for it.
// It is a little difficult to distinguish between a symbol name, and
// an instruction flag like 'gds'. In order to do this, we parse
// all tokens as expressions and then treate the symbol name as the token
// string when we want to interpret the operand as a token.
const auto &Tok = Parser.getTok();
SMLoc S = Tok.getLoc();
const MCExpr *Expr = nullptr;
if (!Parser.parseExpression(Expr)) {
Operands.push_back(AMDGPUOperand::CreateExpr(Expr, S));
return MatchOperand_Success;
}
Operands.push_back(AMDGPUOperand::CreateToken(Tok.getString(), Tok.getLoc()));
Parser.Lex();
return MatchOperand_Success;
@ -2774,6 +2810,14 @@ unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
case MCK_offen:
return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
case MCK_SSrc32:
// When operands have expression values, they will return true for isToken,
// because it is not possible to distinguish between a token and an
// expression at parse time. MatchInstructionImpl() will always try to
// match an operand as a token, when isToken returns true, and when the
// name of the expression is not a valid token, the match will fail,
// so we need to handle it here.
return Operand.isSSrc32() ? Match_Success : Match_InvalidOperand;
default: return Match_InvalidOperand;
}
}

View File

@ -0,0 +1,31 @@
// RUN: llvm-mc -arch=amdgcn -mcpu=fiji -show-encoding %s | FileCheck %s --check-prefix=VI
.globl global
.globl gds
// Parse a global expression
s_mov_b32 s0, global
// VI: s_mov_b32 s0, global ; encoding: [0xff,0x00,0x80,0xbe,A,A,A,A]
// VI-NEXT: ; fixup A - offset: 4, value: global, kind: FK_PCRel_4
// Use a token with the same name as a global
ds_gws_init v2 gds
// VI: ds_gws_init v2 gds ; encoding: [0x00,0x00,0x33,0xd8,0x02,0x00,0x00,0x00]
// Use a global with the same name as a token
s_mov_b32 s0, gds
// VI: s_mov_b32 s0, gds ; encoding: [0xff,0x00,0x80,0xbe,A,A,A,A]
// VI-NEXT: ; fixup A - offset: 4, value: gds, kind: FK_PCRel_4
// Use a binary expression
s_mov_b32 s0, gds+4
// VI: s_mov_b32 s0, gds+4 ; encoding: [0xff,0x00,0x80,0xbe,A,A,A,A]
// VI-NEXT: ; fixup A - offset: 4, value: gds+4, kind: FK_PCRel_4
// Consecutive instructions with no blank line in between to make sure we
// don't call Lex() too many times.
s_add_u32 s0, s0, global+4
s_addc_u32 s1, s1, 0
// VI: s_add_u32 s0, s0, global+4
// VI: s_addc_u32 s1, s1, 0