1 //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/SmallVector.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCParser/MCAsmLexer.h"
21 #include "llvm/MC/MCParser/MCAsmParser.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCRegisterInfo.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/MC/MCTargetAsmParser.h"
27 #include "llvm/Support/SourceMgr.h"
28 #include "llvm/Support/TargetRegistry.h"
29 #include "llvm/Support/raw_ostream.h"
35 class AMDGPUAsmParser : public MCTargetAsmParser {
40 /// @name Auto-generated Match Functions
43 #define GET_ASSEMBLER_HEADER
44 #include "AMDGPUGenAsmMatcher.inc"
49 AMDGPUAsmParser(MCSubtargetInfo &STI, MCAsmParser &Parser,
50 const MCInstrInfo &MII, const MCTargetOptions &Options)
51 : MCTargetAsmParser(), STI(STI), Parser(Parser) {
52 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
54 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
55 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
56 OperandVector &Operands, MCStreamer &Out,
58 bool MatchingInlineAsm) override;
59 bool ParseDirective(AsmToken DirectiveID) override;
60 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
61 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
62 SMLoc NameLoc, OperandVector &Operands) override;
64 bool parseCnt(int64_t &IntVal);
65 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
68 class AMDGPUOperand : public MCParsedAsmOperand {
75 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
91 void addImmOperands(MCInst &Inst, unsigned N) const {
92 Inst.addOperand(MCOperand::CreateImm(getImm()));
94 void addRegOperands(MCInst &Inst, unsigned N) const {
95 llvm_unreachable("addRegOperands");
97 StringRef getToken() const {
98 return StringRef(Tok.Data, Tok.Length);
100 bool isToken() const override {
101 return Kind == Token;
104 bool isImm() const override {
105 return Kind == Immediate;
108 int64_t getImm() const {
112 bool isReg() const override {
116 unsigned getReg() const override {
120 bool isMem() const override {
124 SMLoc getStartLoc() const override {
128 SMLoc getEndLoc() const override {
132 void print(raw_ostream &OS) const override { }
134 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val) {
135 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
140 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc) {
141 auto Res = llvm::make_unique<AMDGPUOperand>(Token);
142 Res->Tok.Data = Str.data();
143 Res->Tok.Length = Str.size();
147 bool isSWaitCnt() const;
152 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
157 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
158 OperandVector &Operands,
161 bool MatchingInlineAsm) {
164 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
167 Out.EmitInstruction(Inst, STI);
169 case Match_MissingFeature:
170 return Error(IDLoc, "instruction use requires an option to be enabled");
171 case Match_MnemonicFail:
172 return Error(IDLoc, "unrecognized instruction mnemonic");
173 case Match_InvalidOperand: {
174 if (ErrorInfo != ~0ULL) {
175 if (ErrorInfo >= Operands.size())
176 return Error(IDLoc, "too few operands for instruction");
179 return Error(IDLoc, "invalid operand for instruction");
182 llvm_unreachable("Implement any new match types added!");
185 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
189 AMDGPUAsmParser::OperandMatchResultTy
190 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
192 // Try to parse with a custom parser
193 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
195 // If we successfully parsed the operand or if there as an error parsing,
197 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
200 switch(getLexer().getKind()) {
201 case AsmToken::Integer: {
203 if (getParser().parseAbsoluteExpression(IntVal))
204 return MatchOperand_ParseFail;
205 Operands.push_back(AMDGPUOperand::CreateImm(IntVal));
206 return MatchOperand_Success;
209 return MatchOperand_NoMatch;
213 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
215 SMLoc NameLoc, OperandVector &Operands) {
216 // Add the instruction mnemonic
217 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
219 if (getLexer().is(AsmToken::EndOfStatement))
222 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
224 case MatchOperand_Success: return false;
225 case MatchOperand_ParseFail: return Error(NameLoc,
226 "Failed parsing operand");
227 case MatchOperand_NoMatch: return Error(NameLoc, "Not a valid operand");
232 //===----------------------------------------------------------------------===//
234 //===----------------------------------------------------------------------===//
236 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
237 StringRef CntName = Parser.getTok().getString();
241 if (getLexer().isNot(AsmToken::LParen))
245 if (getLexer().isNot(AsmToken::Integer))
248 if (getParser().parseAbsoluteExpression(CntVal))
251 if (getLexer().isNot(AsmToken::RParen))
255 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
261 if (CntName == "vmcnt") {
264 } else if (CntName == "expcnt") {
267 } else if (CntName == "lgkmcnt") {
274 IntVal &= ~(CntMask << CntShift);
275 IntVal |= (CntVal << CntShift);
279 AMDGPUAsmParser::OperandMatchResultTy
280 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
281 // Disable all counters by default.
285 int64_t CntVal = 0x77f;
287 switch(getLexer().getKind()) {
288 default: return MatchOperand_ParseFail;
289 case AsmToken::Integer:
290 // The operand can be an integer value.
291 if (getParser().parseAbsoluteExpression(CntVal))
292 return MatchOperand_ParseFail;
295 case AsmToken::Identifier:
297 if (parseCnt(CntVal))
298 return MatchOperand_ParseFail;
299 } while(getLexer().isNot(AsmToken::EndOfStatement));
302 Operands.push_back(AMDGPUOperand::CreateImm(CntVal));
303 return MatchOperand_Success;
306 bool AMDGPUOperand::isSWaitCnt() const {
310 /// Force static initialization.
311 extern "C" void LLVMInitializeR600AsmParser() {
312 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
313 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget);
316 #define GET_REGISTER_MATCHER
317 #define GET_MATCHER_IMPLEMENTATION
318 #include "AMDGPUGenAsmMatcher.inc"