Skip to content

Commit

Permalink
[SPARC][IAS] Rework ASI/Prefetch tag matching in prep for `ParseForAl…
Browse files Browse the repository at this point in the history
…lFeatures`

Unify parts of ASI and Prefetch tag matching at `parseASITag`
and `parsePrefetchTag` to use a common function to parse any immediate
expressions. This introduces a slight regression to error messages,
but is needed so we can enable `ParseForAllFeatures`
in `MatchOperandParserImpl` in a future patch.

Reviewers: jrtc27, brad0, rorth, s-barannikov

Reviewed By: s-barannikov

Pull Request: llvm#96020
  • Loading branch information
koachan authored Jun 27, 2024
1 parent 468d668 commit e9b8cd0
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 51 deletions.
126 changes: 79 additions & 47 deletions llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,15 @@ class SparcAsmParser : public MCTargetAsmParser {

ParseStatus parseBranchModifiers(OperandVector &Operands);

ParseStatus parseExpression(int64_t &Val);

// Helper function for dealing with %lo / %hi in PIC mode.
const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
const MCExpr *subExpr);

// Helper function to see if current token can start an expression.
bool isPossibleExpression(const AsmToken &Token);

// returns true if Tok is matched to a register and returns register in RegNo.
MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);

Expand Down Expand Up @@ -1085,32 +1090,35 @@ ParseStatus SparcAsmParser::parseASITag(OperandVector &Operands) {
SMLoc E = Parser.getTok().getEndLoc();
int64_t ASIVal = 0;

if (is64Bit() && (getLexer().getKind() == AsmToken::Hash)) {
// For now we only support named tags for 64-bit/V9 systems.
// TODO: add support for 32-bit/V8 systems.
SMLoc TagStart = getLexer().peekTok(false).getLoc();
Parser.Lex(); // Eat the '#'.
auto ASIName = Parser.getTok().getString();
auto ASITag = SparcASITag::lookupASITagByName(ASIName);
if (!ASITag)
ASITag = SparcASITag::lookupASITagByAltName(ASIName);
Parser.Lex(); // Eat the identifier token.
if (getLexer().getKind() != AsmToken::Hash) {
// If the ASI tag provided is not a named tag, then it
// must be a constant expression.
ParseStatus ParseExprStatus = parseExpression(ASIVal);
if (!ParseExprStatus.isSuccess())
return ParseExprStatus;

if (!ASITag)
return Error(TagStart, "unknown ASI tag");

ASIVal = ASITag->Encoding;
} else if (!getParser().parseAbsoluteExpression(ASIVal)) {
if (!isUInt<8>(ASIVal))
return Error(S, "invalid ASI number, must be between 0 and 255");
} else {
return Error(
S, is64Bit()
? "malformed ASI tag, must be %asi, a constant integer "
"expression, or a named tag"
: "malformed ASI tag, must be a constant integer expression");

Operands.push_back(SparcOperand::CreateASITag(ASIVal, S, E));
return ParseStatus::Success;
}

// For now we only support named tags for 64-bit/V9 systems.
// TODO: add support for 32-bit/V8 systems.
SMLoc TagStart = getLexer().peekTok(false).getLoc();
Parser.Lex(); // Eat the '#'.
const StringRef ASIName = Parser.getTok().getString();
const SparcASITag::ASITag *ASITag = SparcASITag::lookupASITagByName(ASIName);
if (!ASITag)
ASITag = SparcASITag::lookupASITagByAltName(ASIName);
Parser.Lex(); // Eat the identifier token.

if (!ASITag)
return Error(TagStart, "unknown ASI tag");

ASIVal = ASITag->Encoding;

Operands.push_back(SparcOperand::CreateASITag(ASIVal, S, E));
return ParseStatus::Success;
}
Expand All @@ -1120,35 +1128,32 @@ ParseStatus SparcAsmParser::parsePrefetchTag(OperandVector &Operands) {
SMLoc E = Parser.getTok().getEndLoc();
int64_t PrefetchVal = 0;

switch (getLexer().getKind()) {
case AsmToken::LParen:
case AsmToken::Integer:
case AsmToken::Identifier:
case AsmToken::Plus:
case AsmToken::Minus:
case AsmToken::Tilde:
if (getParser().parseAbsoluteExpression(PrefetchVal) ||
!isUInt<5>(PrefetchVal))
return Error(S, "invalid prefetch number, must be between 0 and 31");
break;
case AsmToken::Hash: {
SMLoc TagStart = getLexer().peekTok(false).getLoc();
Parser.Lex(); // Eat the '#'.
const StringRef PrefetchName = Parser.getTok().getString();
const SparcPrefetchTag::PrefetchTag *PrefetchTag =
SparcPrefetchTag::lookupPrefetchTagByName(PrefetchName);
Parser.Lex(); // Eat the identifier token.
if (getLexer().getKind() != AsmToken::Hash) {
// If the prefetch tag provided is not a named tag, then it
// must be a constant expression.
ParseStatus ParseExprStatus = parseExpression(PrefetchVal);
if (!ParseExprStatus.isSuccess())
return ParseExprStatus;

if (!PrefetchTag)
return Error(TagStart, "unknown prefetch tag");
if (!isUInt<8>(PrefetchVal))
return Error(S, "invalid prefetch number, must be between 0 and 31");

PrefetchVal = PrefetchTag->Encoding;
break;
}
default:
return ParseStatus::NoMatch;
Operands.push_back(SparcOperand::CreatePrefetchTag(PrefetchVal, S, E));
return ParseStatus::Success;
}

SMLoc TagStart = getLexer().peekTok(false).getLoc();
Parser.Lex(); // Eat the '#'.
const StringRef PrefetchName = Parser.getTok().getString();
const SparcPrefetchTag::PrefetchTag *PrefetchTag =
SparcPrefetchTag::lookupPrefetchTagByName(PrefetchName);
Parser.Lex(); // Eat the identifier token.

if (!PrefetchTag)
return Error(TagStart, "unknown prefetch tag");

PrefetchVal = PrefetchTag->Encoding;

Operands.push_back(SparcOperand::CreatePrefetchTag(PrefetchVal, S, E));
return ParseStatus::Success;
}
Expand Down Expand Up @@ -1230,8 +1235,12 @@ ParseStatus SparcAsmParser::parseOperand(OperandVector &Operands,
// Parse an optional address-space identifier after the address.
// This will be either an immediate constant expression, or, on 64-bit
// processors, the %asi register.
if (is64Bit() && getLexer().is(AsmToken::Percent)) {
if (getLexer().is(AsmToken::Percent)) {
SMLoc S = Parser.getTok().getLoc();
if (!is64Bit())
return Error(
S, "malformed ASI tag, must be a constant integer expression");

Parser.Lex(); // Eat the %.
const AsmToken Tok = Parser.getTok();
if (Tok.is(AsmToken::Identifier) && Tok.getString() == "asi") {
Expand Down Expand Up @@ -1360,6 +1369,15 @@ ParseStatus SparcAsmParser::parseBranchModifiers(OperandVector &Operands) {
return ParseStatus::Success;
}

ParseStatus SparcAsmParser::parseExpression(int64_t &Val) {
AsmToken Tok = getLexer().getTok();

if (!isPossibleExpression(Tok))
return ParseStatus::NoMatch;

return getParser().parseAbsoluteExpression(Val);
}

#define GET_REGISTER_MATCHER
#include "SparcGenAsmMatcher.inc"

Expand Down Expand Up @@ -1590,6 +1608,20 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
return true;
}

bool SparcAsmParser::isPossibleExpression(const AsmToken &Token) {
switch (Token.getKind()) {
case AsmToken::LParen:
case AsmToken::Integer:
case AsmToken::Identifier:
case AsmToken::Plus:
case AsmToken::Minus:
case AsmToken::Tilde:
return true;
default:
return false;
}
}

extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser() {
RegisterMCAsmParser<SparcAsmParser> A(getTheSparcTarget());
RegisterMCAsmParser<SparcAsmParser> B(getTheSparcV9Target());
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/Sparc/sparc-mem-asi-instructions.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
! RUN: not llvm-mc %s -triple=sparc -show-encoding 2>&1 | FileCheck %s --check-prefix=V8
! RUN: not llvm-mc %s -triple=sparcv9 -show-encoding 2>&1 | FileCheck %s --check-prefix=V9

! V8: error: malformed ASI tag, must be a constant integer expression
! V8: error: expected absolute expression
! V8-NEXT: lduba [%i0] asi, %o2
! V9: error: malformed ASI tag, must be %asi, a constant integer expression, or a named tag
! V9: error: unexpected token
! V9-NEXT: lduba [%i0] asi, %o2
lduba [%i0] asi, %o2

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/MC/Sparc/sparcv9-instructions.s
Original file line number Diff line number Diff line change
Expand Up @@ -657,12 +657,12 @@
! V9: prefetcha [%i1+3968] %asi, #one_read ! encoding: [0xc3,0xee,0x6f,0x80]
prefetcha [ %i1 + 0xf80 ] %asi, #one_read

! V8: error: malformed ASI tag, must be a constant integer expression
! V8: error: invalid operand for instruction
! V8-NEXT: prefetcha [ %i1 + %i2 ] #ASI_SNF, 1
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] #ASI_SNF, 1

! V8: error: malformed ASI tag, must be a constant integer expression
! V8: error: unexpected token
! V8-NEXT: prefetcha [ %i1 + %i2 ] #ASI_SNF, #one_read
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] #ASI_SNF, #one_read
Expand Down

0 comments on commit e9b8cd0

Please sign in to comment.