OSDN Git Service

am 876d6995: Merge "Update aosp/master LLVM for rebase to r222494."
[android-x86/external-llvm.git] / lib / Target / R600 / AsmParser / AMDGPUAsmParser.cpp
1 //===-- 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
31 using namespace llvm;
32
33 namespace {
34
35 class 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
48 public:
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
69 class AMDGPUOperand : public MCParsedAsmOperand {
70   enum KindTy {
71     Token,
72     Immediate
73   } Kind;
74
75 public:
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
153 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
154   return true;
155 }
156
157
158 bool 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
187 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
188   return true;
189 }
190
191 AMDGPUAsmParser::OperandMatchResultTy
192 AMDGPUAsmParser::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
215 bool 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
238 bool 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
281 AMDGPUAsmParser::OperandMatchResultTy
282 AMDGPUAsmParser::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
308 bool AMDGPUOperand::isSWaitCnt() const {
309   return isImm();
310 }
311
312 /// Force static initialization.
313 extern "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