blob: 7ad815dbcac8819998ccb8bf59cfd8b0cdfbb769 [file] [log] [blame]
Tom Stellard9d7ddd52014-11-14 14:08:00 +00001//===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
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"
30
31using namespace llvm;
32
33namespace {
34
35class AMDGPUAsmParser : public MCTargetAsmParser {
36 MCSubtargetInfo &STI;
37 MCAsmParser &Parser;
38
39
40 /// @name Auto-generated Match Functions
41 /// {
42
43#define GET_ASSEMBLER_HEADER
44#include "AMDGPUGenAsmMatcher.inc"
45
46 /// }
47
48public:
49 AMDGPUAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser,
50 const MCInstrInfo &_MII,
51 const MCTargetOptions &Options)
52 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
53 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
54 }
55 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
56 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
57 OperandVector &Operands, MCStreamer &Out,
58 uint64_t &ErrorInfo,
59 bool MatchingInlineAsm) override;
60 bool ParseDirective(AsmToken DirectiveID) override;
61 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
62 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
63 SMLoc NameLoc, OperandVector &Operands) override;
64
65 bool parseCnt(int64_t &IntVal);
66 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
67};
68
69class AMDGPUOperand : public MCParsedAsmOperand {
70 enum KindTy {
71 Token,
72 Immediate
73 } Kind;
74
75public:
76 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
77
78 struct TokOp {
79 const char *Data;
80 unsigned Length;
81 };
82
83 struct ImmOp {
84 int64_t Val;
85 };
86
87 union {
88 TokOp Tok;
89 ImmOp Imm;
90 };
91
92 void addImmOperands(MCInst &Inst, unsigned N) const {
93 Inst.addOperand(MCOperand::CreateImm(getImm()));
94 }
95 void addRegOperands(MCInst &Inst, unsigned N) const {
96 llvm_unreachable("addRegOperands");
97 }
98 StringRef getToken() const {
99 return StringRef(Tok.Data, Tok.Length);
100 }
101 bool isToken() const override {
102 return Kind == Token;
103 }
104
105 bool isImm() const override {
106 return Kind == Immediate;
107 }
108
109 int64_t getImm() const {
110 return Imm.Val;
111 }
112
113 bool isReg() const override {
114 return false;
115 }
116
117 unsigned getReg() const override {
118 return 0;
119 }
120
121 bool isMem() const override {
122 return false;
123 }
124
125 SMLoc getStartLoc() const override {
126 return SMLoc();
127 }
128
129 SMLoc getEndLoc() const override {
130 return SMLoc();
131 }
132
133 void print(raw_ostream &OS) const override { }
134
135 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val) {
136 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
137 Op->Imm.Val = Val;
138 return Op;
139 }
140
141 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc) {
142 auto Res = llvm::make_unique<AMDGPUOperand>(Token);
143 Res->Tok.Data = Str.data();
144 Res->Tok.Length = Str.size();
145 return Res;
146 }
147
148 bool isSWaitCnt() const;
149};
150
151}
152
153bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
154 return true;
155}
156
157
158bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
159 OperandVector &Operands,
160 MCStreamer &Out,
161 uint64_t &ErrorInfo,
162 bool MatchingInlineAsm) {
163 MCInst Inst;
164
165 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
166 default: break;
167 case Match_Success:
168 Inst.setLoc(IDLoc);
169 Out.EmitInstruction(Inst, STI);
170 return false;
171 case Match_MissingFeature:
172 return Error(IDLoc, "instruction use requires an option to be enabled");
173 case Match_MnemonicFail:
174 return Error(IDLoc, "unrecognized instruction mnemonic");
175 case Match_InvalidOperand: {
176 if (ErrorInfo != ~0ULL) {
177 if (ErrorInfo >= Operands.size())
178 return Error(IDLoc, "too few operands for instruction");
179
180 }
181 return Error(IDLoc, "invalid operand for instruction");
182 }
183 }
184 llvm_unreachable("Implement any new match types added!");
185}
186
187bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
188 return true;
189}
190
191AMDGPUAsmParser::OperandMatchResultTy
192AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
193
194 // Try to parse with a custom parser
195 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
196
197 // If we successfully parsed the operand or if there as an error parsing,
198 // we are done.
199 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
200 return ResTy;
201
202 switch(getLexer().getKind()) {
203 case AsmToken::Integer: {
204 int64_t IntVal;
205 if (getParser().parseAbsoluteExpression(IntVal))
206 return MatchOperand_ParseFail;
207 Operands.push_back(AMDGPUOperand::CreateImm(IntVal));
208 return MatchOperand_Success;
209 }
210 default:
211 return MatchOperand_NoMatch;
212 }
213}
214
215bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
216 StringRef Name,
217 SMLoc NameLoc, OperandVector &Operands) {
218 // Add the instruction mnemonic
219 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
220
221 if (getLexer().is(AsmToken::EndOfStatement))
222 return false;
223
224 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
225 switch (Res) {
226 case MatchOperand_Success: return false;
227 case MatchOperand_ParseFail: return Error(NameLoc,
228 "Failed parsing operand");
229 case MatchOperand_NoMatch: return Error(NameLoc, "Not a valid operand");
230 }
231 return true;
232}
233
234//===----------------------------------------------------------------------===//
235// s_waitcnt
236//===----------------------------------------------------------------------===//
237
238bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
239 StringRef CntName = Parser.getTok().getString();
240 int64_t CntVal;
241
242 Parser.Lex();
243 if (getLexer().isNot(AsmToken::LParen))
244 return true;
245
246 Parser.Lex();
247 if (getLexer().isNot(AsmToken::Integer))
248 return true;
249
250 if (getParser().parseAbsoluteExpression(CntVal))
251 return true;
252
253 if (getLexer().isNot(AsmToken::RParen))
254 return true;
255
256 Parser.Lex();
257 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
258 Parser.Lex();
259
260 int CntShift;
261 int CntMask;
262
263 if (CntName == "vmcnt") {
264 CntMask = 0xf;
265 CntShift = 0;
266 } else if (CntName == "expcnt") {
267 CntMask = 0x7;
268 CntShift = 4;
269 } else if (CntName == "lgkmcnt") {
270 CntMask = 0x7;
271 CntShift = 8;
272 } else {
273 return true;
274 }
275
276 IntVal &= ~(CntMask << CntShift);
277 IntVal |= (CntVal << CntShift);
278 return false;
279}
280
281AMDGPUAsmParser::OperandMatchResultTy
282AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
283 // Disable all counters by default.
284 // vmcnt [3:0]
285 // expcnt [6:4]
286 // lgkmcnt [10:8]
287 int64_t CntVal = 0x77f;
288
289 switch(getLexer().getKind()) {
290 default: return MatchOperand_ParseFail;
291 case AsmToken::Integer:
292 // The operand can be an integer value.
293 if (getParser().parseAbsoluteExpression(CntVal))
294 return MatchOperand_ParseFail;
295 break;
296
297 case AsmToken::Identifier:
298 do {
299 if (parseCnt(CntVal))
300 return MatchOperand_ParseFail;
301 } while(getLexer().isNot(AsmToken::EndOfStatement));
302 break;
303 }
304 Operands.push_back(AMDGPUOperand::CreateImm(CntVal));
305 return MatchOperand_Success;
306}
307
308bool AMDGPUOperand::isSWaitCnt() const {
309 return isImm();
310}
311
312/// Force static initialization.
313extern "C" void LLVMInitializeR600AsmParser() {
314 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
315}
316
317#define GET_REGISTER_MATCHER
318#define GET_MATCHER_IMPLEMENTATION
319#include "AMDGPUGenAsmMatcher.inc"
320