@@ -1685,24 +1685,48 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
1685
1685
private:
1686
1686
struct OperandInfoTy {
1687
1687
SMLoc Loc;
1688
- int64_t Id ;
1688
+ int64_t Val ;
1689
1689
bool IsSymbolic = false ;
1690
1690
bool IsDefined = false ;
1691
1691
1692
- OperandInfoTy (int64_t Id_ ) : Id(Id_ ) {}
1692
+ OperandInfoTy (int64_t Val ) : Val(Val ) {}
1693
1693
};
1694
1694
1695
+ struct StructuredOpField : OperandInfoTy {
1696
+ StringLiteral Id;
1697
+ StringLiteral Desc;
1698
+ unsigned Width;
1699
+ bool IsDefined = false ;
1700
+
1701
+ StructuredOpField (StringLiteral Id, StringLiteral Desc, unsigned Width,
1702
+ int64_t Default)
1703
+ : OperandInfoTy(Default), Id(Id), Desc(Desc), Width(Width) {}
1704
+ virtual ~StructuredOpField () = default ;
1705
+
1706
+ bool Error (AMDGPUAsmParser &Parser, const Twine &Err) const {
1707
+ Parser.Error (Loc, " invalid " + Desc + " : " + Err);
1708
+ return false ;
1709
+ }
1710
+
1711
+ virtual bool validate (AMDGPUAsmParser &Parser) const {
1712
+ if (IsSymbolic && Val == OPR_ID_UNSUPPORTED)
1713
+ return Error (Parser, " not supported on this GPU" );
1714
+ if (!isUIntN (Width, Val))
1715
+ return Error (Parser, " only " + Twine (Width) + " -bit values are legal" );
1716
+ return true ;
1717
+ }
1718
+ };
1719
+
1720
+ ParseStatus parseStructuredOpFields (ArrayRef<StructuredOpField *> Fields);
1721
+ bool validateStructuredOpFields (ArrayRef<const StructuredOpField *> Fields);
1722
+
1695
1723
bool parseSendMsgBody (OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream);
1696
1724
bool validateSendMsg (const OperandInfoTy &Msg,
1697
1725
const OperandInfoTy &Op,
1698
1726
const OperandInfoTy &Stream);
1699
1727
1700
- bool parseHwregBody (OperandInfoTy &HwReg,
1701
- OperandInfoTy &Offset,
1702
- OperandInfoTy &Width);
1703
- bool validateHwreg (const OperandInfoTy &HwReg,
1704
- const OperandInfoTy &Offset,
1705
- const OperandInfoTy &Width);
1728
+ ParseStatus parseHwregFunc (OperandInfoTy &HwReg, OperandInfoTy &Offset,
1729
+ OperandInfoTy &Width);
1706
1730
1707
1731
SMLoc getFlatOffsetLoc (const OperandVector &Operands) const ;
1708
1732
SMLoc getSMEMOffsetLoc (const OperandVector &Operands) const ;
@@ -7197,71 +7221,44 @@ bool AMDGPUOperand::isDepCtr() const { return isS16Imm(); }
7197
7221
// hwreg
7198
7222
// ===----------------------------------------------------------------------===//
7199
7223
7200
- bool
7201
- AMDGPUAsmParser::parseHwregBody (OperandInfoTy &HwReg,
7202
- OperandInfoTy &Offset,
7203
- OperandInfoTy &Width) {
7224
+ ParseStatus AMDGPUAsmParser::parseHwregFunc (OperandInfoTy &HwReg,
7225
+ OperandInfoTy &Offset,
7226
+ OperandInfoTy &Width) {
7204
7227
using namespace llvm ::AMDGPU::Hwreg;
7205
7228
7229
+ if (!trySkipId (" hwreg" , AsmToken::LParen))
7230
+ return ParseStatus::NoMatch;
7231
+
7206
7232
// The register may be specified by name or using a numeric code
7207
7233
HwReg.Loc = getLoc ();
7208
7234
if (isToken (AsmToken::Identifier) &&
7209
- (HwReg.Id = getHwregId (getTokenStr (), getSTI ())) != OPR_ID_UNKNOWN) {
7235
+ (HwReg.Val = getHwregId (getTokenStr (), getSTI ())) != OPR_ID_UNKNOWN) {
7210
7236
HwReg.IsSymbolic = true ;
7211
7237
lex (); // skip register name
7212
- } else if (!parseExpr (HwReg.Id , " a register name" )) {
7213
- return false ;
7238
+ } else if (!parseExpr (HwReg.Val , " a register name" )) {
7239
+ return ParseStatus::Failure ;
7214
7240
}
7215
7241
7216
7242
if (trySkipToken (AsmToken::RParen))
7217
- return true ;
7243
+ return ParseStatus::Success ;
7218
7244
7219
7245
// parse optional params
7220
7246
if (!skipToken (AsmToken::Comma, " expected a comma or a closing parenthesis" ))
7221
- return false ;
7247
+ return ParseStatus::Failure ;
7222
7248
7223
7249
Offset.Loc = getLoc ();
7224
- if (!parseExpr (Offset.Id ))
7225
- return false ;
7250
+ if (!parseExpr (Offset.Val ))
7251
+ return ParseStatus::Failure ;
7226
7252
7227
7253
if (!skipToken (AsmToken::Comma, " expected a comma" ))
7228
- return false ;
7254
+ return ParseStatus::Failure ;
7229
7255
7230
7256
Width.Loc = getLoc ();
7231
- return parseExpr (Width.Id ) &&
7232
- skipToken (AsmToken::RParen, " expected a closing parenthesis" );
7233
- }
7234
-
7235
- bool
7236
- AMDGPUAsmParser::validateHwreg (const OperandInfoTy &HwReg,
7237
- const OperandInfoTy &Offset,
7238
- const OperandInfoTy &Width) {
7239
-
7240
- using namespace llvm ::AMDGPU::Hwreg;
7257
+ if (!parseExpr (Width.Val ) ||
7258
+ !skipToken (AsmToken::RParen, " expected a closing parenthesis" ))
7259
+ return ParseStatus::Failure;
7241
7260
7242
- if (HwReg.IsSymbolic ) {
7243
- if (HwReg.Id == OPR_ID_UNSUPPORTED) {
7244
- Error (HwReg.Loc ,
7245
- " specified hardware register is not supported on this GPU" );
7246
- return false ;
7247
- }
7248
- } else {
7249
- if (!isValidHwreg (HwReg.Id )) {
7250
- Error (HwReg.Loc ,
7251
- " invalid code of hardware register: only 6-bit values are legal" );
7252
- return false ;
7253
- }
7254
- }
7255
- if (!isValidHwregOffset (Offset.Id )) {
7256
- Error (Offset.Loc , " invalid bit offset: only 5-bit values are legal" );
7257
- return false ;
7258
- }
7259
- if (!isValidHwregWidth (Width.Id )) {
7260
- Error (Width.Loc ,
7261
- " invalid bitfield width: only values from 1 to 32 are legal" );
7262
- return false ;
7263
- }
7264
- return true ;
7261
+ return ParseStatus::Success;
7265
7262
}
7266
7263
7267
7264
ParseStatus AMDGPUAsmParser::parseHwreg (OperandVector &Operands) {
@@ -7270,24 +7267,40 @@ ParseStatus AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
7270
7267
int64_t ImmVal = 0 ;
7271
7268
SMLoc Loc = getLoc ();
7272
7269
7273
- if (trySkipId (" hwreg" , AsmToken::LParen)) {
7274
- OperandInfoTy HwReg (OPR_ID_UNKNOWN);
7275
- OperandInfoTy Offset (HwregOffset::Default);
7276
- OperandInfoTy Width (HwregSize::Default);
7277
- if (parseHwregBody (HwReg, Offset, Width) &&
7278
- validateHwreg (HwReg, Offset, Width)) {
7279
- ImmVal = HwregEncoding::encode (HwReg.Id , Offset.Id , Width.Id );
7280
- } else {
7281
- return ParseStatus::Failure;
7270
+ StructuredOpField HwReg (" id" , " hardware register" , HwregId::Width,
7271
+ HwregId::Default);
7272
+ StructuredOpField Offset (" offset" , " bit offset" , HwregOffset::Width,
7273
+ HwregOffset::Default);
7274
+ struct : StructuredOpField {
7275
+ using StructuredOpField::StructuredOpField;
7276
+ bool validate (AMDGPUAsmParser &Parser) const override {
7277
+ if (!isUIntN (Width, Val - 1 ))
7278
+ return Error (Parser, " only values from 1 to 32 are legal" );
7279
+ return true ;
7282
7280
}
7283
- } else if (parseExpr (ImmVal, " a hwreg macro" )) {
7284
- if (ImmVal < 0 || !isUInt<16 >(ImmVal))
7285
- return Error (Loc, " invalid immediate: only 16-bit values are legal" );
7286
- } else {
7287
- return ParseStatus::Failure;
7281
+ } Width (" size" , " bitfield width" , HwregSize::Width, HwregSize::Default);
7282
+ ParseStatus Res = parseStructuredOpFields ({&HwReg, &Offset, &Width});
7283
+
7284
+ if (Res.isNoMatch ())
7285
+ Res = parseHwregFunc (HwReg, Offset, Width);
7286
+
7287
+ if (Res.isSuccess ()) {
7288
+ if (!validateStructuredOpFields ({&HwReg, &Offset, &Width}))
7289
+ return ParseStatus::Failure;
7290
+ ImmVal = HwregEncoding::encode (HwReg.Val , Offset.Val , Width.Val );
7288
7291
}
7289
7292
7290
- Operands.push_back (AMDGPUOperand::CreateImm (this , ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
7293
+ if (Res.isNoMatch () &&
7294
+ parseExpr (ImmVal, " a hwreg macro, structured immediate" ))
7295
+ Res = ParseStatus::Success;
7296
+
7297
+ if (!Res.isSuccess ())
7298
+ return ParseStatus::Failure;
7299
+
7300
+ if (!isUInt<16 >(ImmVal))
7301
+ return Error (Loc, " invalid immediate: only 16-bit values are legal" );
7302
+ Operands.push_back (
7303
+ AMDGPUOperand::CreateImm (this , ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
7291
7304
return ParseStatus::Success;
7292
7305
}
7293
7306
@@ -7307,27 +7320,27 @@ AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg,
7307
7320
7308
7321
Msg.Loc = getLoc ();
7309
7322
if (isToken (AsmToken::Identifier) &&
7310
- (Msg.Id = getMsgId (getTokenStr (), getSTI ())) != OPR_ID_UNKNOWN) {
7323
+ (Msg.Val = getMsgId (getTokenStr (), getSTI ())) != OPR_ID_UNKNOWN) {
7311
7324
Msg.IsSymbolic = true ;
7312
7325
lex (); // skip message name
7313
- } else if (!parseExpr (Msg.Id , " a message name" )) {
7326
+ } else if (!parseExpr (Msg.Val , " a message name" )) {
7314
7327
return false ;
7315
7328
}
7316
7329
7317
7330
if (trySkipToken (AsmToken::Comma)) {
7318
7331
Op.IsDefined = true ;
7319
7332
Op.Loc = getLoc ();
7320
7333
if (isToken (AsmToken::Identifier) &&
7321
- (Op.Id = getMsgOpId (Msg.Id , getTokenStr ())) >= 0 ) {
7334
+ (Op.Val = getMsgOpId (Msg.Val , getTokenStr ())) >= 0 ) {
7322
7335
lex (); // skip operation name
7323
- } else if (!parseExpr (Op.Id , " an operation name" )) {
7336
+ } else if (!parseExpr (Op.Val , " an operation name" )) {
7324
7337
return false ;
7325
7338
}
7326
7339
7327
7340
if (trySkipToken (AsmToken::Comma)) {
7328
7341
Stream.IsDefined = true ;
7329
7342
Stream.Loc = getLoc ();
7330
- if (!parseExpr (Stream.Id ))
7343
+ if (!parseExpr (Stream.Val ))
7331
7344
return false ;
7332
7345
}
7333
7346
}
@@ -7347,34 +7360,34 @@ AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
7347
7360
bool Strict = Msg.IsSymbolic ;
7348
7361
7349
7362
if (Strict) {
7350
- if (Msg.Id == OPR_ID_UNSUPPORTED) {
7363
+ if (Msg.Val == OPR_ID_UNSUPPORTED) {
7351
7364
Error (Msg.Loc , " specified message id is not supported on this GPU" );
7352
7365
return false ;
7353
7366
}
7354
7367
} else {
7355
- if (!isValidMsgId (Msg.Id , getSTI ())) {
7368
+ if (!isValidMsgId (Msg.Val , getSTI ())) {
7356
7369
Error (Msg.Loc , " invalid message id" );
7357
7370
return false ;
7358
7371
}
7359
7372
}
7360
- if (Strict && (msgRequiresOp (Msg.Id , getSTI ()) != Op.IsDefined )) {
7373
+ if (Strict && (msgRequiresOp (Msg.Val , getSTI ()) != Op.IsDefined )) {
7361
7374
if (Op.IsDefined ) {
7362
7375
Error (Op.Loc , " message does not support operations" );
7363
7376
} else {
7364
7377
Error (Msg.Loc , " missing message operation" );
7365
7378
}
7366
7379
return false ;
7367
7380
}
7368
- if (!isValidMsgOp (Msg.Id , Op.Id , getSTI (), Strict)) {
7381
+ if (!isValidMsgOp (Msg.Val , Op.Val , getSTI (), Strict)) {
7369
7382
Error (Op.Loc , " invalid operation id" );
7370
7383
return false ;
7371
7384
}
7372
- if (Strict && !msgSupportsStream (Msg.Id , Op.Id , getSTI ()) &&
7385
+ if (Strict && !msgSupportsStream (Msg.Val , Op.Val , getSTI ()) &&
7373
7386
Stream.IsDefined ) {
7374
7387
Error (Stream.Loc , " message operation does not support streams" );
7375
7388
return false ;
7376
7389
}
7377
- if (!isValidMsgStream (Msg.Id , Op.Id , Stream.Id , getSTI (), Strict)) {
7390
+ if (!isValidMsgStream (Msg.Val , Op.Val , Stream.Val , getSTI (), Strict)) {
7378
7391
Error (Stream.Loc , " invalid message stream id" );
7379
7392
return false ;
7380
7393
}
@@ -7393,7 +7406,7 @@ ParseStatus AMDGPUAsmParser::parseSendMsg(OperandVector &Operands) {
7393
7406
OperandInfoTy Stream (STREAM_ID_NONE_);
7394
7407
if (parseSendMsgBody (Msg, Op, Stream) &&
7395
7408
validateSendMsg (Msg, Op, Stream)) {
7396
- ImmVal = encodeMsg (Msg.Id , Op.Id , Stream.Id );
7409
+ ImmVal = encodeMsg (Msg.Val , Op.Val , Stream.Val );
7397
7410
} else {
7398
7411
return ParseStatus::Failure;
7399
7412
}
@@ -7730,6 +7743,48 @@ AMDGPUAsmParser::getConstLoc(const OperandVector &Operands) const {
7730
7743
return getOperandLoc (Test, Operands);
7731
7744
}
7732
7745
7746
+ ParseStatus
7747
+ AMDGPUAsmParser::parseStructuredOpFields (ArrayRef<StructuredOpField *> Fields) {
7748
+ if (!trySkipToken (AsmToken::LCurly))
7749
+ return ParseStatus::NoMatch;
7750
+
7751
+ bool First = true ;
7752
+ while (!trySkipToken (AsmToken::RCurly)) {
7753
+ if (!First &&
7754
+ !skipToken (AsmToken::Comma, " comma or closing brace expected" ))
7755
+ return ParseStatus::Failure;
7756
+
7757
+ StringRef Id = getTokenStr ();
7758
+ SMLoc IdLoc = getLoc ();
7759
+ if (!skipToken (AsmToken::Identifier, " field name expected" ) ||
7760
+ !skipToken (AsmToken::Colon, " colon expected" ))
7761
+ return ParseStatus::Failure;
7762
+
7763
+ auto I =
7764
+ find_if (Fields, [Id](StructuredOpField *F) { return F->Id == Id; });
7765
+ if (I == Fields.end ())
7766
+ return Error (IdLoc, " unknown field" );
7767
+ if ((*I)->IsDefined )
7768
+ return Error (IdLoc, " duplicate field" );
7769
+
7770
+ // TODO: Support symbolic values.
7771
+ (*I)->Loc = getLoc ();
7772
+ if (!parseExpr ((*I)->Val ))
7773
+ return ParseStatus::Failure;
7774
+ (*I)->IsDefined = true ;
7775
+
7776
+ First = false ;
7777
+ }
7778
+ return ParseStatus::Success;
7779
+ }
7780
+
7781
+ bool AMDGPUAsmParser::validateStructuredOpFields (
7782
+ ArrayRef<const StructuredOpField *> Fields) {
7783
+ return all_of (Fields, [this ](const StructuredOpField *F) {
7784
+ return F->validate (*this );
7785
+ });
7786
+ }
7787
+
7733
7788
// ===----------------------------------------------------------------------===//
7734
7789
// swizzle
7735
7790
// ===----------------------------------------------------------------------===//
0 commit comments