summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp48
1 files changed, 46 insertions, 2 deletions
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 12303a67c27..752f0cd2c39 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -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;
}
}
OpenPOWER on IntegriCloud