File: | lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp |
Warning: | line 1157, column 30 The left operand of '!=' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- SystemZAsmParser.cpp - Parse SystemZ assembly 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/SystemZMCTargetDesc.h" | |||
11 | #include "llvm/ADT/STLExtras.h" | |||
12 | #include "llvm/ADT/SmallVector.h" | |||
13 | #include "llvm/ADT/StringRef.h" | |||
14 | #include "llvm/MC/MCContext.h" | |||
15 | #include "llvm/MC/MCExpr.h" | |||
16 | #include "llvm/MC/MCInst.h" | |||
17 | #include "llvm/MC/MCInstBuilder.h" | |||
18 | #include "llvm/MC/MCParser/MCAsmLexer.h" | |||
19 | #include "llvm/MC/MCParser/MCAsmParser.h" | |||
20 | #include "llvm/MC/MCParser/MCAsmParserExtension.h" | |||
21 | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" | |||
22 | #include "llvm/MC/MCParser/MCTargetAsmParser.h" | |||
23 | #include "llvm/MC/MCStreamer.h" | |||
24 | #include "llvm/MC/MCSubtargetInfo.h" | |||
25 | #include "llvm/Support/Casting.h" | |||
26 | #include "llvm/Support/ErrorHandling.h" | |||
27 | #include "llvm/Support/SMLoc.h" | |||
28 | #include "llvm/Support/TargetRegistry.h" | |||
29 | #include <algorithm> | |||
30 | #include <cassert> | |||
31 | #include <cstddef> | |||
32 | #include <cstdint> | |||
33 | #include <iterator> | |||
34 | #include <memory> | |||
35 | #include <string> | |||
36 | ||||
37 | using namespace llvm; | |||
38 | ||||
39 | // Return true if Expr is in the range [MinValue, MaxValue]. | |||
40 | static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { | |||
41 | if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { | |||
42 | int64_t Value = CE->getValue(); | |||
43 | return Value >= MinValue && Value <= MaxValue; | |||
44 | } | |||
45 | return false; | |||
46 | } | |||
47 | ||||
48 | namespace { | |||
49 | ||||
50 | enum RegisterKind { | |||
51 | GR32Reg, | |||
52 | GRH32Reg, | |||
53 | GR64Reg, | |||
54 | GR128Reg, | |||
55 | ADDR32Reg, | |||
56 | ADDR64Reg, | |||
57 | FP32Reg, | |||
58 | FP64Reg, | |||
59 | FP128Reg, | |||
60 | VR32Reg, | |||
61 | VR64Reg, | |||
62 | VR128Reg, | |||
63 | AR32Reg, | |||
64 | CR64Reg, | |||
65 | }; | |||
66 | ||||
67 | enum MemoryKind { | |||
68 | BDMem, | |||
69 | BDXMem, | |||
70 | BDLMem, | |||
71 | BDRMem, | |||
72 | BDVMem | |||
73 | }; | |||
74 | ||||
75 | class SystemZOperand : public MCParsedAsmOperand { | |||
76 | private: | |||
77 | enum OperandKind { | |||
78 | KindInvalid, | |||
79 | KindToken, | |||
80 | KindReg, | |||
81 | KindImm, | |||
82 | KindImmTLS, | |||
83 | KindMem | |||
84 | }; | |||
85 | ||||
86 | OperandKind Kind; | |||
87 | SMLoc StartLoc, EndLoc; | |||
88 | ||||
89 | // A string of length Length, starting at Data. | |||
90 | struct TokenOp { | |||
91 | const char *Data; | |||
92 | unsigned Length; | |||
93 | }; | |||
94 | ||||
95 | // LLVM register Num, which has kind Kind. In some ways it might be | |||
96 | // easier for this class to have a register bank (general, floating-point | |||
97 | // or access) and a raw register number (0-15). This would postpone the | |||
98 | // interpretation of the operand to the add*() methods and avoid the need | |||
99 | // for context-dependent parsing. However, we do things the current way | |||
100 | // because of the virtual getReg() method, which needs to distinguish | |||
101 | // between (say) %r0 used as a single register and %r0 used as a pair. | |||
102 | // Context-dependent parsing can also give us slightly better error | |||
103 | // messages when invalid pairs like %r1 are used. | |||
104 | struct RegOp { | |||
105 | RegisterKind Kind; | |||
106 | unsigned Num; | |||
107 | }; | |||
108 | ||||
109 | // Base + Disp + Index, where Base and Index are LLVM registers or 0. | |||
110 | // MemKind says what type of memory this is and RegKind says what type | |||
111 | // the base register has (ADDR32Reg or ADDR64Reg). Length is the operand | |||
112 | // length for D(L,B)-style operands, otherwise it is null. | |||
113 | struct MemOp { | |||
114 | unsigned Base : 12; | |||
115 | unsigned Index : 12; | |||
116 | unsigned MemKind : 4; | |||
117 | unsigned RegKind : 4; | |||
118 | const MCExpr *Disp; | |||
119 | union { | |||
120 | const MCExpr *Imm; | |||
121 | unsigned Reg; | |||
122 | } Length; | |||
123 | }; | |||
124 | ||||
125 | // Imm is an immediate operand, and Sym is an optional TLS symbol | |||
126 | // for use with a __tls_get_offset marker relocation. | |||
127 | struct ImmTLSOp { | |||
128 | const MCExpr *Imm; | |||
129 | const MCExpr *Sym; | |||
130 | }; | |||
131 | ||||
132 | union { | |||
133 | TokenOp Token; | |||
134 | RegOp Reg; | |||
135 | const MCExpr *Imm; | |||
136 | ImmTLSOp ImmTLS; | |||
137 | MemOp Mem; | |||
138 | }; | |||
139 | ||||
140 | void addExpr(MCInst &Inst, const MCExpr *Expr) const { | |||
141 | // Add as immediates when possible. Null MCExpr = 0. | |||
142 | if (!Expr) | |||
143 | Inst.addOperand(MCOperand::createImm(0)); | |||
144 | else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) | |||
145 | Inst.addOperand(MCOperand::createImm(CE->getValue())); | |||
146 | else | |||
147 | Inst.addOperand(MCOperand::createExpr(Expr)); | |||
148 | } | |||
149 | ||||
150 | public: | |||
151 | SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc) | |||
152 | : Kind(kind), StartLoc(startLoc), EndLoc(endLoc) {} | |||
153 | ||||
154 | // Create particular kinds of operand. | |||
155 | static std::unique_ptr<SystemZOperand> createInvalid(SMLoc StartLoc, | |||
156 | SMLoc EndLoc) { | |||
157 | return make_unique<SystemZOperand>(KindInvalid, StartLoc, EndLoc); | |||
158 | } | |||
159 | ||||
160 | static std::unique_ptr<SystemZOperand> createToken(StringRef Str, SMLoc Loc) { | |||
161 | auto Op = make_unique<SystemZOperand>(KindToken, Loc, Loc); | |||
162 | Op->Token.Data = Str.data(); | |||
163 | Op->Token.Length = Str.size(); | |||
164 | return Op; | |||
165 | } | |||
166 | ||||
167 | static std::unique_ptr<SystemZOperand> | |||
168 | createReg(RegisterKind Kind, unsigned Num, SMLoc StartLoc, SMLoc EndLoc) { | |||
169 | auto Op = make_unique<SystemZOperand>(KindReg, StartLoc, EndLoc); | |||
170 | Op->Reg.Kind = Kind; | |||
171 | Op->Reg.Num = Num; | |||
172 | return Op; | |||
173 | } | |||
174 | ||||
175 | static std::unique_ptr<SystemZOperand> | |||
176 | createImm(const MCExpr *Expr, SMLoc StartLoc, SMLoc EndLoc) { | |||
177 | auto Op = make_unique<SystemZOperand>(KindImm, StartLoc, EndLoc); | |||
178 | Op->Imm = Expr; | |||
179 | return Op; | |||
180 | } | |||
181 | ||||
182 | static std::unique_ptr<SystemZOperand> | |||
183 | createMem(MemoryKind MemKind, RegisterKind RegKind, unsigned Base, | |||
184 | const MCExpr *Disp, unsigned Index, const MCExpr *LengthImm, | |||
185 | unsigned LengthReg, SMLoc StartLoc, SMLoc EndLoc) { | |||
186 | auto Op = make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc); | |||
187 | Op->Mem.MemKind = MemKind; | |||
188 | Op->Mem.RegKind = RegKind; | |||
189 | Op->Mem.Base = Base; | |||
190 | Op->Mem.Index = Index; | |||
191 | Op->Mem.Disp = Disp; | |||
192 | if (MemKind == BDLMem) | |||
193 | Op->Mem.Length.Imm = LengthImm; | |||
194 | if (MemKind == BDRMem) | |||
195 | Op->Mem.Length.Reg = LengthReg; | |||
196 | return Op; | |||
197 | } | |||
198 | ||||
199 | static std::unique_ptr<SystemZOperand> | |||
200 | createImmTLS(const MCExpr *Imm, const MCExpr *Sym, | |||
201 | SMLoc StartLoc, SMLoc EndLoc) { | |||
202 | auto Op = make_unique<SystemZOperand>(KindImmTLS, StartLoc, EndLoc); | |||
203 | Op->ImmTLS.Imm = Imm; | |||
204 | Op->ImmTLS.Sym = Sym; | |||
205 | return Op; | |||
206 | } | |||
207 | ||||
208 | // Token operands | |||
209 | bool isToken() const override { | |||
210 | return Kind == KindToken; | |||
211 | } | |||
212 | StringRef getToken() const { | |||
213 | assert(Kind == KindToken && "Not a token")(static_cast <bool> (Kind == KindToken && "Not a token" ) ? void (0) : __assert_fail ("Kind == KindToken && \"Not a token\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 213, __extension__ __PRETTY_FUNCTION__)); | |||
214 | return StringRef(Token.Data, Token.Length); | |||
215 | } | |||
216 | ||||
217 | // Register operands. | |||
218 | bool isReg() const override { | |||
219 | return Kind == KindReg; | |||
220 | } | |||
221 | bool isReg(RegisterKind RegKind) const { | |||
222 | return Kind == KindReg && Reg.Kind == RegKind; | |||
223 | } | |||
224 | unsigned getReg() const override { | |||
225 | assert(Kind == KindReg && "Not a register")(static_cast <bool> (Kind == KindReg && "Not a register" ) ? void (0) : __assert_fail ("Kind == KindReg && \"Not a register\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 225, __extension__ __PRETTY_FUNCTION__)); | |||
226 | return Reg.Num; | |||
227 | } | |||
228 | ||||
229 | // Immediate operands. | |||
230 | bool isImm() const override { | |||
231 | return Kind == KindImm; | |||
232 | } | |||
233 | bool isImm(int64_t MinValue, int64_t MaxValue) const { | |||
234 | return Kind == KindImm && inRange(Imm, MinValue, MaxValue); | |||
235 | } | |||
236 | const MCExpr *getImm() const { | |||
237 | assert(Kind == KindImm && "Not an immediate")(static_cast <bool> (Kind == KindImm && "Not an immediate" ) ? void (0) : __assert_fail ("Kind == KindImm && \"Not an immediate\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 237, __extension__ __PRETTY_FUNCTION__)); | |||
238 | return Imm; | |||
239 | } | |||
240 | ||||
241 | // Immediate operands with optional TLS symbol. | |||
242 | bool isImmTLS() const { | |||
243 | return Kind == KindImmTLS; | |||
244 | } | |||
245 | ||||
246 | // Memory operands. | |||
247 | bool isMem() const override { | |||
248 | return Kind == KindMem; | |||
249 | } | |||
250 | bool isMem(MemoryKind MemKind) const { | |||
251 | return (Kind == KindMem && | |||
252 | (Mem.MemKind == MemKind || | |||
253 | // A BDMem can be treated as a BDXMem in which the index | |||
254 | // register field is 0. | |||
255 | (Mem.MemKind == BDMem && MemKind == BDXMem))); | |||
256 | } | |||
257 | bool isMem(MemoryKind MemKind, RegisterKind RegKind) const { | |||
258 | return isMem(MemKind) && Mem.RegKind == RegKind; | |||
259 | } | |||
260 | bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const { | |||
261 | return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff); | |||
262 | } | |||
263 | bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const { | |||
264 | return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287); | |||
265 | } | |||
266 | bool isMemDisp12Len4(RegisterKind RegKind) const { | |||
267 | return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10); | |||
268 | } | |||
269 | bool isMemDisp12Len8(RegisterKind RegKind) const { | |||
270 | return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x100); | |||
271 | } | |||
272 | ||||
273 | // Override MCParsedAsmOperand. | |||
274 | SMLoc getStartLoc() const override { return StartLoc; } | |||
275 | SMLoc getEndLoc() const override { return EndLoc; } | |||
276 | void print(raw_ostream &OS) const override; | |||
277 | ||||
278 | /// getLocRange - Get the range between the first and last token of this | |||
279 | /// operand. | |||
280 | SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } | |||
281 | ||||
282 | // Used by the TableGen code to add particular types of operand | |||
283 | // to an instruction. | |||
284 | void addRegOperands(MCInst &Inst, unsigned N) const { | |||
285 | assert(N == 1 && "Invalid number of operands")(static_cast <bool> (N == 1 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 285, __extension__ __PRETTY_FUNCTION__)); | |||
286 | Inst.addOperand(MCOperand::createReg(getReg())); | |||
287 | } | |||
288 | void addImmOperands(MCInst &Inst, unsigned N) const { | |||
289 | assert(N == 1 && "Invalid number of operands")(static_cast <bool> (N == 1 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 289, __extension__ __PRETTY_FUNCTION__)); | |||
290 | addExpr(Inst, getImm()); | |||
291 | } | |||
292 | void addBDAddrOperands(MCInst &Inst, unsigned N) const { | |||
293 | assert(N == 2 && "Invalid number of operands")(static_cast <bool> (N == 2 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 293, __extension__ __PRETTY_FUNCTION__)); | |||
294 | assert(isMem(BDMem) && "Invalid operand type")(static_cast <bool> (isMem(BDMem) && "Invalid operand type" ) ? void (0) : __assert_fail ("isMem(BDMem) && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 294, __extension__ __PRETTY_FUNCTION__)); | |||
295 | Inst.addOperand(MCOperand::createReg(Mem.Base)); | |||
296 | addExpr(Inst, Mem.Disp); | |||
297 | } | |||
298 | void addBDXAddrOperands(MCInst &Inst, unsigned N) const { | |||
299 | assert(N == 3 && "Invalid number of operands")(static_cast <bool> (N == 3 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 299, __extension__ __PRETTY_FUNCTION__)); | |||
300 | assert(isMem(BDXMem) && "Invalid operand type")(static_cast <bool> (isMem(BDXMem) && "Invalid operand type" ) ? void (0) : __assert_fail ("isMem(BDXMem) && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 300, __extension__ __PRETTY_FUNCTION__)); | |||
301 | Inst.addOperand(MCOperand::createReg(Mem.Base)); | |||
302 | addExpr(Inst, Mem.Disp); | |||
303 | Inst.addOperand(MCOperand::createReg(Mem.Index)); | |||
304 | } | |||
305 | void addBDLAddrOperands(MCInst &Inst, unsigned N) const { | |||
306 | assert(N == 3 && "Invalid number of operands")(static_cast <bool> (N == 3 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 306, __extension__ __PRETTY_FUNCTION__)); | |||
307 | assert(isMem(BDLMem) && "Invalid operand type")(static_cast <bool> (isMem(BDLMem) && "Invalid operand type" ) ? void (0) : __assert_fail ("isMem(BDLMem) && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 307, __extension__ __PRETTY_FUNCTION__)); | |||
308 | Inst.addOperand(MCOperand::createReg(Mem.Base)); | |||
309 | addExpr(Inst, Mem.Disp); | |||
310 | addExpr(Inst, Mem.Length.Imm); | |||
311 | } | |||
312 | void addBDRAddrOperands(MCInst &Inst, unsigned N) const { | |||
313 | assert(N == 3 && "Invalid number of operands")(static_cast <bool> (N == 3 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 313, __extension__ __PRETTY_FUNCTION__)); | |||
314 | assert(isMem(BDRMem) && "Invalid operand type")(static_cast <bool> (isMem(BDRMem) && "Invalid operand type" ) ? void (0) : __assert_fail ("isMem(BDRMem) && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 314, __extension__ __PRETTY_FUNCTION__)); | |||
315 | Inst.addOperand(MCOperand::createReg(Mem.Base)); | |||
316 | addExpr(Inst, Mem.Disp); | |||
317 | Inst.addOperand(MCOperand::createReg(Mem.Length.Reg)); | |||
318 | } | |||
319 | void addBDVAddrOperands(MCInst &Inst, unsigned N) const { | |||
320 | assert(N == 3 && "Invalid number of operands")(static_cast <bool> (N == 3 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 3 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 320, __extension__ __PRETTY_FUNCTION__)); | |||
321 | assert(isMem(BDVMem) && "Invalid operand type")(static_cast <bool> (isMem(BDVMem) && "Invalid operand type" ) ? void (0) : __assert_fail ("isMem(BDVMem) && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 321, __extension__ __PRETTY_FUNCTION__)); | |||
322 | Inst.addOperand(MCOperand::createReg(Mem.Base)); | |||
323 | addExpr(Inst, Mem.Disp); | |||
324 | Inst.addOperand(MCOperand::createReg(Mem.Index)); | |||
325 | } | |||
326 | void addImmTLSOperands(MCInst &Inst, unsigned N) const { | |||
327 | assert(N == 2 && "Invalid number of operands")(static_cast <bool> (N == 2 && "Invalid number of operands" ) ? void (0) : __assert_fail ("N == 2 && \"Invalid number of operands\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 327, __extension__ __PRETTY_FUNCTION__)); | |||
328 | assert(Kind == KindImmTLS && "Invalid operand type")(static_cast <bool> (Kind == KindImmTLS && "Invalid operand type" ) ? void (0) : __assert_fail ("Kind == KindImmTLS && \"Invalid operand type\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 328, __extension__ __PRETTY_FUNCTION__)); | |||
329 | addExpr(Inst, ImmTLS.Imm); | |||
330 | if (ImmTLS.Sym) | |||
331 | addExpr(Inst, ImmTLS.Sym); | |||
332 | } | |||
333 | ||||
334 | // Used by the TableGen code to check for particular operand types. | |||
335 | bool isGR32() const { return isReg(GR32Reg); } | |||
336 | bool isGRH32() const { return isReg(GRH32Reg); } | |||
337 | bool isGRX32() const { return false; } | |||
338 | bool isGR64() const { return isReg(GR64Reg); } | |||
339 | bool isGR128() const { return isReg(GR128Reg); } | |||
340 | bool isADDR32() const { return isReg(ADDR32Reg); } | |||
341 | bool isADDR64() const { return isReg(ADDR64Reg); } | |||
342 | bool isADDR128() const { return false; } | |||
343 | bool isFP32() const { return isReg(FP32Reg); } | |||
344 | bool isFP64() const { return isReg(FP64Reg); } | |||
345 | bool isFP128() const { return isReg(FP128Reg); } | |||
346 | bool isVR32() const { return isReg(VR32Reg); } | |||
347 | bool isVR64() const { return isReg(VR64Reg); } | |||
348 | bool isVF128() const { return false; } | |||
349 | bool isVR128() const { return isReg(VR128Reg); } | |||
350 | bool isAR32() const { return isReg(AR32Reg); } | |||
351 | bool isCR64() const { return isReg(CR64Reg); } | |||
352 | bool isAnyReg() const { return (isReg() || isImm(0, 15)); } | |||
353 | bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, ADDR32Reg); } | |||
354 | bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, ADDR32Reg); } | |||
355 | bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, ADDR64Reg); } | |||
356 | bool isBDAddr64Disp20() const { return isMemDisp20(BDMem, ADDR64Reg); } | |||
357 | bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, ADDR64Reg); } | |||
358 | bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, ADDR64Reg); } | |||
359 | bool isBDLAddr64Disp12Len4() const { return isMemDisp12Len4(ADDR64Reg); } | |||
360 | bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(ADDR64Reg); } | |||
361 | bool isBDRAddr64Disp12() const { return isMemDisp12(BDRMem, ADDR64Reg); } | |||
362 | bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, ADDR64Reg); } | |||
363 | bool isU1Imm() const { return isImm(0, 1); } | |||
364 | bool isU2Imm() const { return isImm(0, 3); } | |||
365 | bool isU3Imm() const { return isImm(0, 7); } | |||
366 | bool isU4Imm() const { return isImm(0, 15); } | |||
367 | bool isU6Imm() const { return isImm(0, 63); } | |||
368 | bool isU8Imm() const { return isImm(0, 255); } | |||
369 | bool isS8Imm() const { return isImm(-128, 127); } | |||
370 | bool isU12Imm() const { return isImm(0, 4095); } | |||
371 | bool isU16Imm() const { return isImm(0, 65535); } | |||
372 | bool isS16Imm() const { return isImm(-32768, 32767); } | |||
373 | bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); } | |||
374 | bool isS32Imm() const { return isImm(-(1LL << 31), (1LL << 31) - 1); } | |||
375 | bool isU48Imm() const { return isImm(0, (1LL << 48) - 1); } | |||
376 | }; | |||
377 | ||||
378 | class SystemZAsmParser : public MCTargetAsmParser { | |||
379 | #define GET_ASSEMBLER_HEADER | |||
380 | #include "SystemZGenAsmMatcher.inc" | |||
381 | ||||
382 | private: | |||
383 | MCAsmParser &Parser; | |||
384 | enum RegisterGroup { | |||
385 | RegGR, | |||
386 | RegFP, | |||
387 | RegV, | |||
388 | RegAR, | |||
389 | RegCR | |||
390 | }; | |||
391 | struct Register { | |||
392 | RegisterGroup Group; | |||
393 | unsigned Num; | |||
394 | SMLoc StartLoc, EndLoc; | |||
395 | }; | |||
396 | ||||
397 | bool parseRegister(Register &Reg); | |||
398 | ||||
399 | bool parseRegister(Register &Reg, RegisterGroup Group, const unsigned *Regs, | |||
400 | bool IsAddress = false); | |||
401 | ||||
402 | OperandMatchResultTy parseRegister(OperandVector &Operands, | |||
403 | RegisterGroup Group, const unsigned *Regs, | |||
404 | RegisterKind Kind); | |||
405 | ||||
406 | OperandMatchResultTy parseAnyRegister(OperandVector &Operands); | |||
407 | ||||
408 | bool parseAddress(bool &HaveReg1, Register &Reg1, | |||
409 | bool &HaveReg2, Register &Reg2, | |||
410 | const MCExpr *&Disp, const MCExpr *&Length); | |||
411 | bool parseAddressRegister(Register &Reg); | |||
412 | ||||
413 | bool ParseDirectiveInsn(SMLoc L); | |||
414 | ||||
415 | OperandMatchResultTy parseAddress(OperandVector &Operands, | |||
416 | MemoryKind MemKind, const unsigned *Regs, | |||
417 | RegisterKind RegKind); | |||
418 | ||||
419 | OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal, | |||
420 | int64_t MaxVal, bool AllowTLS); | |||
421 | ||||
422 | bool parseOperand(OperandVector &Operands, StringRef Mnemonic); | |||
423 | ||||
424 | public: | |||
425 | SystemZAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser, | |||
426 | const MCInstrInfo &MII, | |||
427 | const MCTargetOptions &Options) | |||
428 | : MCTargetAsmParser(Options, sti, MII), Parser(parser) { | |||
429 | MCAsmParserExtension::Initialize(Parser); | |||
430 | ||||
431 | // Alias the .word directive to .short. | |||
432 | parser.addAliasForDirective(".word", ".short"); | |||
433 | ||||
434 | // Initialize the set of available features. | |||
435 | setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); | |||
436 | } | |||
437 | ||||
438 | // Override MCTargetAsmParser. | |||
439 | bool ParseDirective(AsmToken DirectiveID) override; | |||
440 | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; | |||
441 | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | |||
442 | SMLoc NameLoc, OperandVector &Operands) override; | |||
443 | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | |||
444 | OperandVector &Operands, MCStreamer &Out, | |||
445 | uint64_t &ErrorInfo, | |||
446 | bool MatchingInlineAsm) override; | |||
447 | ||||
448 | // Used by the TableGen code to parse particular operand types. | |||
449 | OperandMatchResultTy parseGR32(OperandVector &Operands) { | |||
450 | return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, GR32Reg); | |||
451 | } | |||
452 | OperandMatchResultTy parseGRH32(OperandVector &Operands) { | |||
453 | return parseRegister(Operands, RegGR, SystemZMC::GRH32Regs, GRH32Reg); | |||
454 | } | |||
455 | OperandMatchResultTy parseGRX32(OperandVector &Operands) { | |||
456 | llvm_unreachable("GRX32 should only be used for pseudo instructions")::llvm::llvm_unreachable_internal("GRX32 should only be used for pseudo instructions" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 456); | |||
457 | } | |||
458 | OperandMatchResultTy parseGR64(OperandVector &Operands) { | |||
459 | return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, GR64Reg); | |||
460 | } | |||
461 | OperandMatchResultTy parseGR128(OperandVector &Operands) { | |||
462 | return parseRegister(Operands, RegGR, SystemZMC::GR128Regs, GR128Reg); | |||
463 | } | |||
464 | OperandMatchResultTy parseADDR32(OperandVector &Operands) { | |||
465 | return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, ADDR32Reg); | |||
466 | } | |||
467 | OperandMatchResultTy parseADDR64(OperandVector &Operands) { | |||
468 | return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, ADDR64Reg); | |||
469 | } | |||
470 | OperandMatchResultTy parseADDR128(OperandVector &Operands) { | |||
471 | llvm_unreachable("Shouldn't be used as an operand")::llvm::llvm_unreachable_internal("Shouldn't be used as an operand" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 471); | |||
472 | } | |||
473 | OperandMatchResultTy parseFP32(OperandVector &Operands) { | |||
474 | return parseRegister(Operands, RegFP, SystemZMC::FP32Regs, FP32Reg); | |||
475 | } | |||
476 | OperandMatchResultTy parseFP64(OperandVector &Operands) { | |||
477 | return parseRegister(Operands, RegFP, SystemZMC::FP64Regs, FP64Reg); | |||
478 | } | |||
479 | OperandMatchResultTy parseFP128(OperandVector &Operands) { | |||
480 | return parseRegister(Operands, RegFP, SystemZMC::FP128Regs, FP128Reg); | |||
481 | } | |||
482 | OperandMatchResultTy parseVR32(OperandVector &Operands) { | |||
483 | return parseRegister(Operands, RegV, SystemZMC::VR32Regs, VR32Reg); | |||
484 | } | |||
485 | OperandMatchResultTy parseVR64(OperandVector &Operands) { | |||
486 | return parseRegister(Operands, RegV, SystemZMC::VR64Regs, VR64Reg); | |||
487 | } | |||
488 | OperandMatchResultTy parseVF128(OperandVector &Operands) { | |||
489 | llvm_unreachable("Shouldn't be used as an operand")::llvm::llvm_unreachable_internal("Shouldn't be used as an operand" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 489); | |||
490 | } | |||
491 | OperandMatchResultTy parseVR128(OperandVector &Operands) { | |||
492 | return parseRegister(Operands, RegV, SystemZMC::VR128Regs, VR128Reg); | |||
493 | } | |||
494 | OperandMatchResultTy parseAR32(OperandVector &Operands) { | |||
495 | return parseRegister(Operands, RegAR, SystemZMC::AR32Regs, AR32Reg); | |||
496 | } | |||
497 | OperandMatchResultTy parseCR64(OperandVector &Operands) { | |||
498 | return parseRegister(Operands, RegCR, SystemZMC::CR64Regs, CR64Reg); | |||
499 | } | |||
500 | OperandMatchResultTy parseAnyReg(OperandVector &Operands) { | |||
501 | return parseAnyRegister(Operands); | |||
502 | } | |||
503 | OperandMatchResultTy parseBDAddr32(OperandVector &Operands) { | |||
504 | return parseAddress(Operands, BDMem, SystemZMC::GR32Regs, ADDR32Reg); | |||
505 | } | |||
506 | OperandMatchResultTy parseBDAddr64(OperandVector &Operands) { | |||
507 | return parseAddress(Operands, BDMem, SystemZMC::GR64Regs, ADDR64Reg); | |||
508 | } | |||
509 | OperandMatchResultTy parseBDXAddr64(OperandVector &Operands) { | |||
510 | return parseAddress(Operands, BDXMem, SystemZMC::GR64Regs, ADDR64Reg); | |||
511 | } | |||
512 | OperandMatchResultTy parseBDLAddr64(OperandVector &Operands) { | |||
513 | return parseAddress(Operands, BDLMem, SystemZMC::GR64Regs, ADDR64Reg); | |||
514 | } | |||
515 | OperandMatchResultTy parseBDRAddr64(OperandVector &Operands) { | |||
516 | return parseAddress(Operands, BDRMem, SystemZMC::GR64Regs, ADDR64Reg); | |||
517 | } | |||
518 | OperandMatchResultTy parseBDVAddr64(OperandVector &Operands) { | |||
519 | return parseAddress(Operands, BDVMem, SystemZMC::GR64Regs, ADDR64Reg); | |||
520 | } | |||
521 | OperandMatchResultTy parsePCRel12(OperandVector &Operands) { | |||
522 | return parsePCRel(Operands, -(1LL << 12), (1LL << 12) - 1, false); | |||
523 | } | |||
524 | OperandMatchResultTy parsePCRel16(OperandVector &Operands) { | |||
525 | return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false); | |||
526 | } | |||
527 | OperandMatchResultTy parsePCRel24(OperandVector &Operands) { | |||
528 | return parsePCRel(Operands, -(1LL << 24), (1LL << 24) - 1, false); | |||
529 | } | |||
530 | OperandMatchResultTy parsePCRel32(OperandVector &Operands) { | |||
531 | return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, false); | |||
532 | } | |||
533 | OperandMatchResultTy parsePCRelTLS16(OperandVector &Operands) { | |||
534 | return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, true); | |||
535 | } | |||
536 | OperandMatchResultTy parsePCRelTLS32(OperandVector &Operands) { | |||
537 | return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1, true); | |||
538 | } | |||
539 | }; | |||
540 | ||||
541 | } // end anonymous namespace | |||
542 | ||||
543 | #define GET_REGISTER_MATCHER | |||
544 | #define GET_SUBTARGET_FEATURE_NAME | |||
545 | #define GET_MATCHER_IMPLEMENTATION | |||
546 | #define GET_MNEMONIC_SPELL_CHECKER | |||
547 | #include "SystemZGenAsmMatcher.inc" | |||
548 | ||||
549 | // Used for the .insn directives; contains information needed to parse the | |||
550 | // operands in the directive. | |||
551 | struct InsnMatchEntry { | |||
552 | StringRef Format; | |||
553 | uint64_t Opcode; | |||
554 | int32_t NumOperands; | |||
555 | MatchClassKind OperandKinds[5]; | |||
556 | }; | |||
557 | ||||
558 | // For equal_range comparison. | |||
559 | struct CompareInsn { | |||
560 | bool operator() (const InsnMatchEntry &LHS, StringRef RHS) { | |||
561 | return LHS.Format < RHS; | |||
562 | } | |||
563 | bool operator() (StringRef LHS, const InsnMatchEntry &RHS) { | |||
564 | return LHS < RHS.Format; | |||
565 | } | |||
566 | bool operator() (const InsnMatchEntry &LHS, const InsnMatchEntry &RHS) { | |||
567 | return LHS.Format < RHS.Format; | |||
568 | } | |||
569 | }; | |||
570 | ||||
571 | // Table initializing information for parsing the .insn directive. | |||
572 | static struct InsnMatchEntry InsnMatchTable[] = { | |||
573 | /* Format, Opcode, NumOperands, OperandKinds */ | |||
574 | { "e", SystemZ::InsnE, 1, | |||
575 | { MCK_U16Imm } }, | |||
576 | { "ri", SystemZ::InsnRI, 3, | |||
577 | { MCK_U32Imm, MCK_AnyReg, MCK_S16Imm } }, | |||
578 | { "rie", SystemZ::InsnRIE, 4, | |||
579 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } }, | |||
580 | { "ril", SystemZ::InsnRIL, 3, | |||
581 | { MCK_U48Imm, MCK_AnyReg, MCK_PCRel32 } }, | |||
582 | { "rilu", SystemZ::InsnRILU, 3, | |||
583 | { MCK_U48Imm, MCK_AnyReg, MCK_U32Imm } }, | |||
584 | { "ris", SystemZ::InsnRIS, 5, | |||
585 | { MCK_U48Imm, MCK_AnyReg, MCK_S8Imm, MCK_U4Imm, MCK_BDAddr64Disp12 } }, | |||
586 | { "rr", SystemZ::InsnRR, 3, | |||
587 | { MCK_U16Imm, MCK_AnyReg, MCK_AnyReg } }, | |||
588 | { "rre", SystemZ::InsnRRE, 3, | |||
589 | { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg } }, | |||
590 | { "rrf", SystemZ::InsnRRF, 5, | |||
591 | { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm } }, | |||
592 | { "rrs", SystemZ::InsnRRS, 5, | |||
593 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_U4Imm, MCK_BDAddr64Disp12 } }, | |||
594 | { "rs", SystemZ::InsnRS, 4, | |||
595 | { MCK_U32Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } }, | |||
596 | { "rse", SystemZ::InsnRSE, 4, | |||
597 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp12 } }, | |||
598 | { "rsi", SystemZ::InsnRSI, 4, | |||
599 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_PCRel16 } }, | |||
600 | { "rsy", SystemZ::InsnRSY, 4, | |||
601 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDAddr64Disp20 } }, | |||
602 | { "rx", SystemZ::InsnRX, 3, | |||
603 | { MCK_U32Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } }, | |||
604 | { "rxe", SystemZ::InsnRXE, 3, | |||
605 | { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp12 } }, | |||
606 | { "rxf", SystemZ::InsnRXF, 4, | |||
607 | { MCK_U48Imm, MCK_AnyReg, MCK_AnyReg, MCK_BDXAddr64Disp12 } }, | |||
608 | { "rxy", SystemZ::InsnRXY, 3, | |||
609 | { MCK_U48Imm, MCK_AnyReg, MCK_BDXAddr64Disp20 } }, | |||
610 | { "s", SystemZ::InsnS, 2, | |||
611 | { MCK_U32Imm, MCK_BDAddr64Disp12 } }, | |||
612 | { "si", SystemZ::InsnSI, 3, | |||
613 | { MCK_U32Imm, MCK_BDAddr64Disp12, MCK_S8Imm } }, | |||
614 | { "sil", SystemZ::InsnSIL, 3, | |||
615 | { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_U16Imm } }, | |||
616 | { "siy", SystemZ::InsnSIY, 3, | |||
617 | { MCK_U48Imm, MCK_BDAddr64Disp20, MCK_U8Imm } }, | |||
618 | { "ss", SystemZ::InsnSS, 4, | |||
619 | { MCK_U48Imm, MCK_BDXAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } }, | |||
620 | { "sse", SystemZ::InsnSSE, 3, | |||
621 | { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12 } }, | |||
622 | { "ssf", SystemZ::InsnSSF, 4, | |||
623 | { MCK_U48Imm, MCK_BDAddr64Disp12, MCK_BDAddr64Disp12, MCK_AnyReg } } | |||
624 | }; | |||
625 | ||||
626 | void SystemZOperand::print(raw_ostream &OS) const { | |||
627 | llvm_unreachable("Not implemented")::llvm::llvm_unreachable_internal("Not implemented", "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 627); | |||
628 | } | |||
629 | ||||
630 | // Parse one register of the form %<prefix><number>. | |||
631 | bool SystemZAsmParser::parseRegister(Register &Reg) { | |||
632 | Reg.StartLoc = Parser.getTok().getLoc(); | |||
633 | ||||
634 | // Eat the % prefix. | |||
635 | if (Parser.getTok().isNot(AsmToken::Percent)) | |||
636 | return Error(Parser.getTok().getLoc(), "register expected"); | |||
637 | Parser.Lex(); | |||
638 | ||||
639 | // Expect a register name. | |||
640 | if (Parser.getTok().isNot(AsmToken::Identifier)) | |||
641 | return Error(Reg.StartLoc, "invalid register"); | |||
642 | ||||
643 | // Check that there's a prefix. | |||
644 | StringRef Name = Parser.getTok().getString(); | |||
645 | if (Name.size() < 2) | |||
646 | return Error(Reg.StartLoc, "invalid register"); | |||
647 | char Prefix = Name[0]; | |||
648 | ||||
649 | // Treat the rest of the register name as a register number. | |||
650 | if (Name.substr(1).getAsInteger(10, Reg.Num)) | |||
651 | return Error(Reg.StartLoc, "invalid register"); | |||
652 | ||||
653 | // Look for valid combinations of prefix and number. | |||
654 | if (Prefix == 'r' && Reg.Num < 16) | |||
655 | Reg.Group = RegGR; | |||
656 | else if (Prefix == 'f' && Reg.Num < 16) | |||
657 | Reg.Group = RegFP; | |||
658 | else if (Prefix == 'v' && Reg.Num < 32) | |||
659 | Reg.Group = RegV; | |||
660 | else if (Prefix == 'a' && Reg.Num < 16) | |||
661 | Reg.Group = RegAR; | |||
662 | else if (Prefix == 'c' && Reg.Num < 16) | |||
663 | Reg.Group = RegCR; | |||
664 | else | |||
665 | return Error(Reg.StartLoc, "invalid register"); | |||
666 | ||||
667 | Reg.EndLoc = Parser.getTok().getLoc(); | |||
668 | Parser.Lex(); | |||
669 | return false; | |||
670 | } | |||
671 | ||||
672 | // Parse a register of group Group. If Regs is nonnull, use it to map | |||
673 | // the raw register number to LLVM numbering, with zero entries | |||
674 | // indicating an invalid register. IsAddress says whether the | |||
675 | // register appears in an address context. Allow FP Group if expecting | |||
676 | // RegV Group, since the f-prefix yields the FP group even while used | |||
677 | // with vector instructions. | |||
678 | bool SystemZAsmParser::parseRegister(Register &Reg, RegisterGroup Group, | |||
679 | const unsigned *Regs, bool IsAddress) { | |||
680 | if (parseRegister(Reg)) | |||
681 | return true; | |||
682 | if (Reg.Group != Group && !(Reg.Group == RegFP && Group == RegV)) | |||
683 | return Error(Reg.StartLoc, "invalid operand for instruction"); | |||
684 | if (Regs && Regs[Reg.Num] == 0) | |||
685 | return Error(Reg.StartLoc, "invalid register pair"); | |||
686 | if (Reg.Num == 0 && IsAddress) | |||
687 | return Error(Reg.StartLoc, "%r0 used in an address"); | |||
688 | if (Regs) | |||
689 | Reg.Num = Regs[Reg.Num]; | |||
690 | return false; | |||
691 | } | |||
692 | ||||
693 | // Parse a register and add it to Operands. The other arguments are as above. | |||
694 | OperandMatchResultTy | |||
695 | SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterGroup Group, | |||
696 | const unsigned *Regs, RegisterKind Kind) { | |||
697 | if (Parser.getTok().isNot(AsmToken::Percent)) | |||
698 | return MatchOperand_NoMatch; | |||
699 | ||||
700 | Register Reg; | |||
701 | bool IsAddress = (Kind == ADDR32Reg || Kind == ADDR64Reg); | |||
702 | if (parseRegister(Reg, Group, Regs, IsAddress)) | |||
703 | return MatchOperand_ParseFail; | |||
704 | ||||
705 | Operands.push_back(SystemZOperand::createReg(Kind, Reg.Num, | |||
706 | Reg.StartLoc, Reg.EndLoc)); | |||
707 | return MatchOperand_Success; | |||
708 | } | |||
709 | ||||
710 | // Parse any type of register (including integers) and add it to Operands. | |||
711 | OperandMatchResultTy | |||
712 | SystemZAsmParser::parseAnyRegister(OperandVector &Operands) { | |||
713 | // Handle integer values. | |||
714 | if (Parser.getTok().is(AsmToken::Integer)) { | |||
715 | const MCExpr *Register; | |||
716 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
717 | if (Parser.parseExpression(Register)) | |||
718 | return MatchOperand_ParseFail; | |||
719 | ||||
720 | if (auto *CE = dyn_cast<MCConstantExpr>(Register)) { | |||
721 | int64_t Value = CE->getValue(); | |||
722 | if (Value < 0 || Value > 15) { | |||
723 | Error(StartLoc, "invalid register"); | |||
724 | return MatchOperand_ParseFail; | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | SMLoc EndLoc = | |||
729 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | |||
730 | ||||
731 | Operands.push_back(SystemZOperand::createImm(Register, StartLoc, EndLoc)); | |||
732 | } | |||
733 | else { | |||
734 | Register Reg; | |||
735 | if (parseRegister(Reg)) | |||
736 | return MatchOperand_ParseFail; | |||
737 | ||||
738 | // Map to the correct register kind. | |||
739 | RegisterKind Kind; | |||
740 | unsigned RegNo; | |||
741 | if (Reg.Group == RegGR) { | |||
742 | Kind = GR64Reg; | |||
743 | RegNo = SystemZMC::GR64Regs[Reg.Num]; | |||
744 | } | |||
745 | else if (Reg.Group == RegFP) { | |||
746 | Kind = FP64Reg; | |||
747 | RegNo = SystemZMC::FP64Regs[Reg.Num]; | |||
748 | } | |||
749 | else if (Reg.Group == RegV) { | |||
750 | Kind = VR128Reg; | |||
751 | RegNo = SystemZMC::VR128Regs[Reg.Num]; | |||
752 | } | |||
753 | else if (Reg.Group == RegAR) { | |||
754 | Kind = AR32Reg; | |||
755 | RegNo = SystemZMC::AR32Regs[Reg.Num]; | |||
756 | } | |||
757 | else if (Reg.Group == RegCR) { | |||
758 | Kind = CR64Reg; | |||
759 | RegNo = SystemZMC::CR64Regs[Reg.Num]; | |||
760 | } | |||
761 | else { | |||
762 | return MatchOperand_ParseFail; | |||
763 | } | |||
764 | ||||
765 | Operands.push_back(SystemZOperand::createReg(Kind, RegNo, | |||
766 | Reg.StartLoc, Reg.EndLoc)); | |||
767 | } | |||
768 | return MatchOperand_Success; | |||
769 | } | |||
770 | ||||
771 | // Parse a memory operand into Reg1, Reg2, Disp, and Length. | |||
772 | bool SystemZAsmParser::parseAddress(bool &HaveReg1, Register &Reg1, | |||
773 | bool &HaveReg2, Register &Reg2, | |||
774 | const MCExpr *&Disp, | |||
775 | const MCExpr *&Length) { | |||
776 | // Parse the displacement, which must always be present. | |||
777 | if (getParser().parseExpression(Disp)) | |||
778 | return true; | |||
779 | ||||
780 | // Parse the optional base and index. | |||
781 | HaveReg1 = false; | |||
782 | HaveReg2 = false; | |||
783 | Length = nullptr; | |||
784 | if (getLexer().is(AsmToken::LParen)) { | |||
785 | Parser.Lex(); | |||
786 | ||||
787 | if (getLexer().is(AsmToken::Percent)) { | |||
788 | // Parse the first register. | |||
789 | HaveReg1 = true; | |||
790 | if (parseRegister(Reg1)) | |||
791 | return true; | |||
792 | } else { | |||
793 | // Parse the length. | |||
794 | if (getParser().parseExpression(Length)) | |||
795 | return true; | |||
796 | } | |||
797 | ||||
798 | // Check whether there's a second register. | |||
799 | if (getLexer().is(AsmToken::Comma)) { | |||
800 | Parser.Lex(); | |||
801 | HaveReg2 = true; | |||
802 | if (parseRegister(Reg2)) | |||
803 | return true; | |||
804 | } | |||
805 | ||||
806 | // Consume the closing bracket. | |||
807 | if (getLexer().isNot(AsmToken::RParen)) | |||
808 | return Error(Parser.getTok().getLoc(), "unexpected token in address"); | |||
809 | Parser.Lex(); | |||
810 | } | |||
811 | return false; | |||
812 | } | |||
813 | ||||
814 | // Verify that Reg is a valid address register (base or index). | |||
815 | bool | |||
816 | SystemZAsmParser::parseAddressRegister(Register &Reg) { | |||
817 | if (Reg.Group == RegV) { | |||
818 | Error(Reg.StartLoc, "invalid use of vector addressing"); | |||
819 | return true; | |||
820 | } else if (Reg.Group != RegGR) { | |||
821 | Error(Reg.StartLoc, "invalid address register"); | |||
822 | return true; | |||
823 | } else if (Reg.Num == 0) { | |||
824 | Error(Reg.StartLoc, "%r0 used in an address"); | |||
825 | return true; | |||
826 | } | |||
827 | return false; | |||
828 | } | |||
829 | ||||
830 | // Parse a memory operand and add it to Operands. The other arguments | |||
831 | // are as above. | |||
832 | OperandMatchResultTy | |||
833 | SystemZAsmParser::parseAddress(OperandVector &Operands, MemoryKind MemKind, | |||
834 | const unsigned *Regs, RegisterKind RegKind) { | |||
835 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
836 | unsigned Base = 0, Index = 0, LengthReg = 0; | |||
837 | Register Reg1, Reg2; | |||
838 | bool HaveReg1, HaveReg2; | |||
839 | const MCExpr *Disp; | |||
840 | const MCExpr *Length; | |||
841 | if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Disp, Length)) | |||
842 | return MatchOperand_ParseFail; | |||
843 | ||||
844 | switch (MemKind) { | |||
845 | case BDMem: | |||
846 | // If we have Reg1, it must be an address register. | |||
847 | if (HaveReg1) { | |||
848 | if (parseAddressRegister(Reg1)) | |||
849 | return MatchOperand_ParseFail; | |||
850 | Base = Regs[Reg1.Num]; | |||
851 | } | |||
852 | // There must be no Reg2 or length. | |||
853 | if (Length) { | |||
854 | Error(StartLoc, "invalid use of length addressing"); | |||
855 | return MatchOperand_ParseFail; | |||
856 | } | |||
857 | if (HaveReg2) { | |||
858 | Error(StartLoc, "invalid use of indexed addressing"); | |||
859 | return MatchOperand_ParseFail; | |||
860 | } | |||
861 | break; | |||
862 | case BDXMem: | |||
863 | // If we have Reg1, it must be an address register. | |||
864 | if (HaveReg1) { | |||
865 | if (parseAddressRegister(Reg1)) | |||
866 | return MatchOperand_ParseFail; | |||
867 | // If the are two registers, the first one is the index and the | |||
868 | // second is the base. | |||
869 | if (HaveReg2) | |||
870 | Index = Regs[Reg1.Num]; | |||
871 | else | |||
872 | Base = Regs[Reg1.Num]; | |||
873 | } | |||
874 | // If we have Reg2, it must be an address register. | |||
875 | if (HaveReg2) { | |||
876 | if (parseAddressRegister(Reg2)) | |||
877 | return MatchOperand_ParseFail; | |||
878 | Base = Regs[Reg2.Num]; | |||
879 | } | |||
880 | // There must be no length. | |||
881 | if (Length) { | |||
882 | Error(StartLoc, "invalid use of length addressing"); | |||
883 | return MatchOperand_ParseFail; | |||
884 | } | |||
885 | break; | |||
886 | case BDLMem: | |||
887 | // If we have Reg2, it must be an address register. | |||
888 | if (HaveReg2) { | |||
889 | if (parseAddressRegister(Reg2)) | |||
890 | return MatchOperand_ParseFail; | |||
891 | Base = Regs[Reg2.Num]; | |||
892 | } | |||
893 | // We cannot support base+index addressing. | |||
894 | if (HaveReg1 && HaveReg2) { | |||
895 | Error(StartLoc, "invalid use of indexed addressing"); | |||
896 | return MatchOperand_ParseFail; | |||
897 | } | |||
898 | // We must have a length. | |||
899 | if (!Length) { | |||
900 | Error(StartLoc, "missing length in address"); | |||
901 | return MatchOperand_ParseFail; | |||
902 | } | |||
903 | break; | |||
904 | case BDRMem: | |||
905 | // We must have Reg1, and it must be a GPR. | |||
906 | if (!HaveReg1 || Reg1.Group != RegGR) { | |||
907 | Error(StartLoc, "invalid operand for instruction"); | |||
908 | return MatchOperand_ParseFail; | |||
909 | } | |||
910 | LengthReg = SystemZMC::GR64Regs[Reg1.Num]; | |||
911 | // If we have Reg2, it must be an address register. | |||
912 | if (HaveReg2) { | |||
913 | if (parseAddressRegister(Reg2)) | |||
914 | return MatchOperand_ParseFail; | |||
915 | Base = Regs[Reg2.Num]; | |||
916 | } | |||
917 | // There must be no length. | |||
918 | if (Length) { | |||
919 | Error(StartLoc, "invalid use of length addressing"); | |||
920 | return MatchOperand_ParseFail; | |||
921 | } | |||
922 | break; | |||
923 | case BDVMem: | |||
924 | // We must have Reg1, and it must be a vector register. | |||
925 | if (!HaveReg1 || Reg1.Group != RegV) { | |||
926 | Error(StartLoc, "vector index required in address"); | |||
927 | return MatchOperand_ParseFail; | |||
928 | } | |||
929 | Index = SystemZMC::VR128Regs[Reg1.Num]; | |||
930 | // If we have Reg2, it must be an address register. | |||
931 | if (HaveReg2) { | |||
932 | if (parseAddressRegister(Reg2)) | |||
933 | return MatchOperand_ParseFail; | |||
934 | Base = Regs[Reg2.Num]; | |||
935 | } | |||
936 | // There must be no length. | |||
937 | if (Length) { | |||
938 | Error(StartLoc, "invalid use of length addressing"); | |||
939 | return MatchOperand_ParseFail; | |||
940 | } | |||
941 | break; | |||
942 | } | |||
943 | ||||
944 | SMLoc EndLoc = | |||
945 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | |||
946 | Operands.push_back(SystemZOperand::createMem(MemKind, RegKind, Base, Disp, | |||
947 | Index, Length, LengthReg, | |||
948 | StartLoc, EndLoc)); | |||
949 | return MatchOperand_Success; | |||
950 | } | |||
951 | ||||
952 | bool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) { | |||
953 | StringRef IDVal = DirectiveID.getIdentifier(); | |||
954 | ||||
955 | if (IDVal == ".insn") | |||
956 | return ParseDirectiveInsn(DirectiveID.getLoc()); | |||
957 | ||||
958 | return true; | |||
959 | } | |||
960 | ||||
961 | /// ParseDirectiveInsn | |||
962 | /// ::= .insn [ format, encoding, (operands (, operands)*) ] | |||
963 | bool SystemZAsmParser::ParseDirectiveInsn(SMLoc L) { | |||
964 | MCAsmParser &Parser = getParser(); | |||
965 | ||||
966 | // Expect instruction format as identifier. | |||
967 | StringRef Format; | |||
968 | SMLoc ErrorLoc = Parser.getTok().getLoc(); | |||
969 | if (Parser.parseIdentifier(Format)) | |||
970 | return Error(ErrorLoc, "expected instruction format"); | |||
971 | ||||
972 | SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands; | |||
973 | ||||
974 | // Find entry for this format in InsnMatchTable. | |||
975 | auto EntryRange = | |||
976 | std::equal_range(std::begin(InsnMatchTable), std::end(InsnMatchTable), | |||
977 | Format, CompareInsn()); | |||
978 | ||||
979 | // If first == second, couldn't find a match in the table. | |||
980 | if (EntryRange.first == EntryRange.second) | |||
981 | return Error(ErrorLoc, "unrecognized format"); | |||
982 | ||||
983 | struct InsnMatchEntry *Entry = EntryRange.first; | |||
984 | ||||
985 | // Format should match from equal_range. | |||
986 | assert(Entry->Format == Format)(static_cast <bool> (Entry->Format == Format) ? void (0) : __assert_fail ("Entry->Format == Format", "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 986, __extension__ __PRETTY_FUNCTION__)); | |||
987 | ||||
988 | // Parse the following operands using the table's information. | |||
989 | for (int i = 0; i < Entry->NumOperands; i++) { | |||
990 | MatchClassKind Kind = Entry->OperandKinds[i]; | |||
991 | ||||
992 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
993 | ||||
994 | // Always expect commas as separators for operands. | |||
995 | if (getLexer().isNot(AsmToken::Comma)) | |||
996 | return Error(StartLoc, "unexpected token in directive"); | |||
997 | Lex(); | |||
998 | ||||
999 | // Parse operands. | |||
1000 | OperandMatchResultTy ResTy; | |||
1001 | if (Kind == MCK_AnyReg) | |||
1002 | ResTy = parseAnyReg(Operands); | |||
1003 | else if (Kind == MCK_BDXAddr64Disp12 || Kind == MCK_BDXAddr64Disp20) | |||
1004 | ResTy = parseBDXAddr64(Operands); | |||
1005 | else if (Kind == MCK_BDAddr64Disp12 || Kind == MCK_BDAddr64Disp20) | |||
1006 | ResTy = parseBDAddr64(Operands); | |||
1007 | else if (Kind == MCK_PCRel32) | |||
1008 | ResTy = parsePCRel32(Operands); | |||
1009 | else if (Kind == MCK_PCRel16) | |||
1010 | ResTy = parsePCRel16(Operands); | |||
1011 | else { | |||
1012 | // Only remaining operand kind is an immediate. | |||
1013 | const MCExpr *Expr; | |||
1014 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
1015 | ||||
1016 | // Expect immediate expression. | |||
1017 | if (Parser.parseExpression(Expr)) | |||
1018 | return Error(StartLoc, "unexpected token in directive"); | |||
1019 | ||||
1020 | SMLoc EndLoc = | |||
1021 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | |||
1022 | ||||
1023 | Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); | |||
1024 | ResTy = MatchOperand_Success; | |||
1025 | } | |||
1026 | ||||
1027 | if (ResTy != MatchOperand_Success) | |||
1028 | return true; | |||
1029 | } | |||
1030 | ||||
1031 | // Build the instruction with the parsed operands. | |||
1032 | MCInst Inst = MCInstBuilder(Entry->Opcode); | |||
1033 | ||||
1034 | for (size_t i = 0; i < Operands.size(); i++) { | |||
1035 | MCParsedAsmOperand &Operand = *Operands[i]; | |||
1036 | MatchClassKind Kind = Entry->OperandKinds[i]; | |||
1037 | ||||
1038 | // Verify operand. | |||
1039 | unsigned Res = validateOperandClass(Operand, Kind); | |||
1040 | if (Res != Match_Success) | |||
1041 | return Error(Operand.getStartLoc(), "unexpected operand type"); | |||
1042 | ||||
1043 | // Add operands to instruction. | |||
1044 | SystemZOperand &ZOperand = static_cast<SystemZOperand &>(Operand); | |||
1045 | if (ZOperand.isReg()) | |||
1046 | ZOperand.addRegOperands(Inst, 1); | |||
1047 | else if (ZOperand.isMem(BDMem)) | |||
1048 | ZOperand.addBDAddrOperands(Inst, 2); | |||
1049 | else if (ZOperand.isMem(BDXMem)) | |||
1050 | ZOperand.addBDXAddrOperands(Inst, 3); | |||
1051 | else if (ZOperand.isImm()) | |||
1052 | ZOperand.addImmOperands(Inst, 1); | |||
1053 | else | |||
1054 | llvm_unreachable("unexpected operand type")::llvm::llvm_unreachable_internal("unexpected operand type", "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 1054); | |||
1055 | } | |||
1056 | ||||
1057 | // Emit as a regular instruction. | |||
1058 | Parser.getStreamer().EmitInstruction(Inst, getSTI()); | |||
1059 | ||||
1060 | return false; | |||
1061 | } | |||
1062 | ||||
1063 | bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, | |||
1064 | SMLoc &EndLoc) { | |||
1065 | Register Reg; | |||
1066 | if (parseRegister(Reg)) | |||
1067 | return true; | |||
1068 | if (Reg.Group == RegGR) | |||
1069 | RegNo = SystemZMC::GR64Regs[Reg.Num]; | |||
1070 | else if (Reg.Group == RegFP) | |||
1071 | RegNo = SystemZMC::FP64Regs[Reg.Num]; | |||
1072 | else if (Reg.Group == RegV) | |||
1073 | RegNo = SystemZMC::VR128Regs[Reg.Num]; | |||
1074 | else if (Reg.Group == RegAR) | |||
1075 | RegNo = SystemZMC::AR32Regs[Reg.Num]; | |||
1076 | else if (Reg.Group == RegCR) | |||
1077 | RegNo = SystemZMC::CR64Regs[Reg.Num]; | |||
1078 | StartLoc = Reg.StartLoc; | |||
1079 | EndLoc = Reg.EndLoc; | |||
1080 | return false; | |||
1081 | } | |||
1082 | ||||
1083 | bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info, | |||
1084 | StringRef Name, SMLoc NameLoc, | |||
1085 | OperandVector &Operands) { | |||
1086 | Operands.push_back(SystemZOperand::createToken(Name, NameLoc)); | |||
1087 | ||||
1088 | // Read the remaining operands. | |||
1089 | if (getLexer().isNot(AsmToken::EndOfStatement)) { | |||
| ||||
1090 | // Read the first operand. | |||
1091 | if (parseOperand(Operands, Name)) { | |||
1092 | return true; | |||
1093 | } | |||
1094 | ||||
1095 | // Read any subsequent operands. | |||
1096 | while (getLexer().is(AsmToken::Comma)) { | |||
1097 | Parser.Lex(); | |||
1098 | if (parseOperand(Operands, Name)) { | |||
1099 | return true; | |||
1100 | } | |||
1101 | } | |||
1102 | if (getLexer().isNot(AsmToken::EndOfStatement)) { | |||
1103 | SMLoc Loc = getLexer().getLoc(); | |||
1104 | return Error(Loc, "unexpected token in argument list"); | |||
1105 | } | |||
1106 | } | |||
1107 | ||||
1108 | // Consume the EndOfStatement. | |||
1109 | Parser.Lex(); | |||
1110 | return false; | |||
1111 | } | |||
1112 | ||||
1113 | bool SystemZAsmParser::parseOperand(OperandVector &Operands, | |||
1114 | StringRef Mnemonic) { | |||
1115 | // Check if the current operand has a custom associated parser, if so, try to | |||
1116 | // custom parse the operand, or fallback to the general approach. Force all | |||
1117 | // features to be available during the operand check, or else we will fail to | |||
1118 | // find the custom parser, and then we will later get an InvalidOperand error | |||
1119 | // instead of a MissingFeature errror. | |||
1120 | uint64_t AvailableFeatures = getAvailableFeatures(); | |||
1121 | setAvailableFeatures(~(uint64_t)0); | |||
1122 | OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); | |||
1123 | setAvailableFeatures(AvailableFeatures); | |||
1124 | if (ResTy == MatchOperand_Success) | |||
1125 | return false; | |||
1126 | ||||
1127 | // If there wasn't a custom match, try the generic matcher below. Otherwise, | |||
1128 | // there was a match, but an error occurred, in which case, just return that | |||
1129 | // the operand parsing failed. | |||
1130 | if (ResTy == MatchOperand_ParseFail) | |||
1131 | return true; | |||
1132 | ||||
1133 | // Check for a register. All real register operands should have used | |||
1134 | // a context-dependent parse routine, which gives the required register | |||
1135 | // class. The code is here to mop up other cases, like those where | |||
1136 | // the instruction isn't recognized. | |||
1137 | if (Parser.getTok().is(AsmToken::Percent)) { | |||
1138 | Register Reg; | |||
1139 | if (parseRegister(Reg)) | |||
1140 | return true; | |||
1141 | Operands.push_back(SystemZOperand::createInvalid(Reg.StartLoc, Reg.EndLoc)); | |||
1142 | return false; | |||
1143 | } | |||
1144 | ||||
1145 | // The only other type of operand is an immediate or address. As above, | |||
1146 | // real address operands should have used a context-dependent parse routine, | |||
1147 | // so we treat any plain expression as an immediate. | |||
1148 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
1149 | Register Reg1, Reg2; | |||
1150 | bool HaveReg1, HaveReg2; | |||
1151 | const MCExpr *Expr; | |||
1152 | const MCExpr *Length; | |||
1153 | if (parseAddress(HaveReg1, Reg1, HaveReg2, Reg2, Expr, Length)) | |||
1154 | return true; | |||
1155 | // If the register combination is not valid for any instruction, reject it. | |||
1156 | // Otherwise, fall back to reporting an unrecognized instruction. | |||
1157 | if (HaveReg1 && Reg1.Group != RegGR && Reg1.Group != RegV | |||
| ||||
1158 | && parseAddressRegister(Reg1)) | |||
1159 | return true; | |||
1160 | if (HaveReg2 && parseAddressRegister(Reg2)) | |||
1161 | return true; | |||
1162 | ||||
1163 | SMLoc EndLoc = | |||
1164 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | |||
1165 | if (HaveReg1 || HaveReg2 || Length) | |||
1166 | Operands.push_back(SystemZOperand::createInvalid(StartLoc, EndLoc)); | |||
1167 | else | |||
1168 | Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); | |||
1169 | return false; | |||
1170 | } | |||
1171 | ||||
1172 | static std::string SystemZMnemonicSpellCheck(StringRef S, uint64_t FBS, | |||
1173 | unsigned VariantID = 0); | |||
1174 | ||||
1175 | bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | |||
1176 | OperandVector &Operands, | |||
1177 | MCStreamer &Out, | |||
1178 | uint64_t &ErrorInfo, | |||
1179 | bool MatchingInlineAsm) { | |||
1180 | MCInst Inst; | |||
1181 | unsigned MatchResult; | |||
1182 | ||||
1183 | MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, | |||
1184 | MatchingInlineAsm); | |||
1185 | switch (MatchResult) { | |||
1186 | case Match_Success: | |||
1187 | Inst.setLoc(IDLoc); | |||
1188 | Out.EmitInstruction(Inst, getSTI()); | |||
1189 | return false; | |||
1190 | ||||
1191 | case Match_MissingFeature: { | |||
1192 | assert(ErrorInfo && "Unknown missing feature!")(static_cast <bool> (ErrorInfo && "Unknown missing feature!" ) ? void (0) : __assert_fail ("ErrorInfo && \"Unknown missing feature!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 1192, __extension__ __PRETTY_FUNCTION__)); | |||
1193 | // Special case the error message for the very common case where only | |||
1194 | // a single subtarget feature is missing | |||
1195 | std::string Msg = "instruction requires:"; | |||
1196 | uint64_t Mask = 1; | |||
1197 | for (unsigned I = 0; I < sizeof(ErrorInfo) * 8 - 1; ++I) { | |||
1198 | if (ErrorInfo & Mask) { | |||
1199 | Msg += " "; | |||
1200 | Msg += getSubtargetFeatureName(ErrorInfo & Mask); | |||
1201 | } | |||
1202 | Mask <<= 1; | |||
1203 | } | |||
1204 | return Error(IDLoc, Msg); | |||
1205 | } | |||
1206 | ||||
1207 | case Match_InvalidOperand: { | |||
1208 | SMLoc ErrorLoc = IDLoc; | |||
1209 | if (ErrorInfo != ~0ULL) { | |||
1210 | if (ErrorInfo >= Operands.size()) | |||
1211 | return Error(IDLoc, "too few operands for instruction"); | |||
1212 | ||||
1213 | ErrorLoc = ((SystemZOperand &)*Operands[ErrorInfo]).getStartLoc(); | |||
1214 | if (ErrorLoc == SMLoc()) | |||
1215 | ErrorLoc = IDLoc; | |||
1216 | } | |||
1217 | return Error(ErrorLoc, "invalid operand for instruction"); | |||
1218 | } | |||
1219 | ||||
1220 | case Match_MnemonicFail: { | |||
1221 | uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); | |||
1222 | std::string Suggestion = SystemZMnemonicSpellCheck( | |||
1223 | ((SystemZOperand &)*Operands[0]).getToken(), FBS); | |||
1224 | return Error(IDLoc, "invalid instruction" + Suggestion, | |||
1225 | ((SystemZOperand &)*Operands[0]).getLocRange()); | |||
1226 | } | |||
1227 | } | |||
1228 | ||||
1229 | llvm_unreachable("Unexpected match type")::llvm::llvm_unreachable_internal("Unexpected match type", "/build/llvm-toolchain-snapshot-7~svn326246/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp" , 1229); | |||
1230 | } | |||
1231 | ||||
1232 | OperandMatchResultTy | |||
1233 | SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal, | |||
1234 | int64_t MaxVal, bool AllowTLS) { | |||
1235 | MCContext &Ctx = getContext(); | |||
1236 | MCStreamer &Out = getStreamer(); | |||
1237 | const MCExpr *Expr; | |||
1238 | SMLoc StartLoc = Parser.getTok().getLoc(); | |||
1239 | if (getParser().parseExpression(Expr)) | |||
1240 | return MatchOperand_NoMatch; | |||
1241 | ||||
1242 | // For consistency with the GNU assembler, treat immediates as offsets | |||
1243 | // from ".". | |||
1244 | if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { | |||
1245 | int64_t Value = CE->getValue(); | |||
1246 | if ((Value & 1) || Value < MinVal || Value > MaxVal) { | |||
1247 | Error(StartLoc, "offset out of range"); | |||
1248 | return MatchOperand_ParseFail; | |||
1249 | } | |||
1250 | MCSymbol *Sym = Ctx.createTempSymbol(); | |||
1251 | Out.EmitLabel(Sym); | |||
1252 | const MCExpr *Base = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, | |||
1253 | Ctx); | |||
1254 | Expr = Value == 0 ? Base : MCBinaryExpr::createAdd(Base, Expr, Ctx); | |||
1255 | } | |||
1256 | ||||
1257 | // Optionally match :tls_gdcall: or :tls_ldcall: followed by a TLS symbol. | |||
1258 | const MCExpr *Sym = nullptr; | |||
1259 | if (AllowTLS && getLexer().is(AsmToken::Colon)) { | |||
1260 | Parser.Lex(); | |||
1261 | ||||
1262 | if (Parser.getTok().isNot(AsmToken::Identifier)) { | |||
1263 | Error(Parser.getTok().getLoc(), "unexpected token"); | |||
1264 | return MatchOperand_ParseFail; | |||
1265 | } | |||
1266 | ||||
1267 | MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; | |||
1268 | StringRef Name = Parser.getTok().getString(); | |||
1269 | if (Name == "tls_gdcall") | |||
1270 | Kind = MCSymbolRefExpr::VK_TLSGD; | |||
1271 | else if (Name == "tls_ldcall") | |||
1272 | Kind = MCSymbolRefExpr::VK_TLSLDM; | |||
1273 | else { | |||
1274 | Error(Parser.getTok().getLoc(), "unknown TLS tag"); | |||
1275 | return MatchOperand_ParseFail; | |||
1276 | } | |||
1277 | Parser.Lex(); | |||
1278 | ||||
1279 | if (Parser.getTok().isNot(AsmToken::Colon)) { | |||
1280 | Error(Parser.getTok().getLoc(), "unexpected token"); | |||
1281 | return MatchOperand_ParseFail; | |||
1282 | } | |||
1283 | Parser.Lex(); | |||
1284 | ||||
1285 | if (Parser.getTok().isNot(AsmToken::Identifier)) { | |||
1286 | Error(Parser.getTok().getLoc(), "unexpected token"); | |||
1287 | return MatchOperand_ParseFail; | |||
1288 | } | |||
1289 | ||||
1290 | StringRef Identifier = Parser.getTok().getString(); | |||
1291 | Sym = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(Identifier), | |||
1292 | Kind, Ctx); | |||
1293 | Parser.Lex(); | |||
1294 | } | |||
1295 | ||||
1296 | SMLoc EndLoc = | |||
1297 | SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | |||
1298 | ||||
1299 | if (AllowTLS) | |||
1300 | Operands.push_back(SystemZOperand::createImmTLS(Expr, Sym, | |||
1301 | StartLoc, EndLoc)); | |||
1302 | else | |||
1303 | Operands.push_back(SystemZOperand::createImm(Expr, StartLoc, EndLoc)); | |||
1304 | ||||
1305 | return MatchOperand_Success; | |||
1306 | } | |||
1307 | ||||
1308 | // Force static initialization. | |||
1309 | extern "C" void LLVMInitializeSystemZAsmParser() { | |||
1310 | RegisterMCAsmParser<SystemZAsmParser> X(getTheSystemZTarget()); | |||
1311 | } |
1 | //===- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks --------*- C++ -*-===// |
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 | #ifndef LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H |
11 | #define LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H |
12 | |
13 | #include "llvm/ADT/STLExtras.h" |
14 | #include "llvm/ADT/StringRef.h" |
15 | #include "llvm/MC/MCParser/MCAsmLexer.h" |
16 | #include "llvm/MC/MCParser/MCAsmParser.h" |
17 | #include "llvm/Support/SMLoc.h" |
18 | |
19 | namespace llvm { |
20 | |
21 | class Twine; |
22 | |
23 | /// \brief Generic interface for extending the MCAsmParser, |
24 | /// which is implemented by target and object file assembly parser |
25 | /// implementations. |
26 | class MCAsmParserExtension { |
27 | MCAsmParser *Parser; |
28 | |
29 | protected: |
30 | MCAsmParserExtension(); |
31 | |
32 | // Helper template for implementing static dispatch functions. |
33 | template<typename T, bool (T::*Handler)(StringRef, SMLoc)> |
34 | static bool HandleDirective(MCAsmParserExtension *Target, |
35 | StringRef Directive, |
36 | SMLoc DirectiveLoc) { |
37 | T *Obj = static_cast<T*>(Target); |
38 | return (Obj->*Handler)(Directive, DirectiveLoc); |
39 | } |
40 | |
41 | bool BracketExpressionsSupported = false; |
42 | |
43 | public: |
44 | MCAsmParserExtension(const MCAsmParserExtension &) = delete; |
45 | MCAsmParserExtension &operator=(const MCAsmParserExtension &) = delete; |
46 | virtual ~MCAsmParserExtension(); |
47 | |
48 | /// \brief Initialize the extension for parsing using the given \p Parser. |
49 | /// The extension should use the AsmParser interfaces to register its |
50 | /// parsing routines. |
51 | virtual void Initialize(MCAsmParser &Parser); |
52 | |
53 | /// \name MCAsmParser Proxy Interfaces |
54 | /// @{ |
55 | |
56 | MCContext &getContext() { return getParser().getContext(); } |
57 | |
58 | MCAsmLexer &getLexer() { return getParser().getLexer(); } |
59 | const MCAsmLexer &getLexer() const { |
60 | return const_cast<MCAsmParserExtension *>(this)->getLexer(); |
61 | } |
62 | |
63 | MCAsmParser &getParser() { return *Parser; } |
64 | const MCAsmParser &getParser() const { |
65 | return const_cast<MCAsmParserExtension*>(this)->getParser(); |
66 | } |
67 | |
68 | SourceMgr &getSourceManager() { return getParser().getSourceManager(); } |
69 | MCStreamer &getStreamer() { return getParser().getStreamer(); } |
70 | |
71 | bool Warning(SMLoc L, const Twine &Msg) { |
72 | return getParser().Warning(L, Msg); |
73 | } |
74 | |
75 | bool Error(SMLoc L, const Twine &Msg, SMRange Range = SMRange()) { |
76 | return getParser().Error(L, Msg, Range); |
77 | } |
78 | |
79 | void Note(SMLoc L, const Twine &Msg) { |
80 | getParser().Note(L, Msg); |
81 | } |
82 | |
83 | bool TokError(const Twine &Msg) { |
84 | return getParser().TokError(Msg); |
85 | } |
86 | |
87 | const AsmToken &Lex() { return getParser().Lex(); } |
88 | const AsmToken &getTok() { return getParser().getTok(); } |
89 | bool parseToken(AsmToken::TokenKind T, |
90 | const Twine &Msg = "unexpected token") { |
91 | return getParser().parseToken(T, Msg); |
92 | } |
93 | |
94 | bool parseMany(function_ref<bool()> parseOne, bool hasComma = true) { |
95 | return getParser().parseMany(parseOne, hasComma); |
96 | } |
97 | |
98 | bool parseOptionalToken(AsmToken::TokenKind T) { |
99 | return getParser().parseOptionalToken(T); |
100 | } |
101 | |
102 | bool check(bool P, const Twine &Msg) { |
103 | return getParser().check(P, Msg); |
104 | } |
105 | |
106 | bool check(bool P, SMLoc Loc, const Twine &Msg) { |
107 | return getParser().check(P, Loc, Msg); |
108 | } |
109 | |
110 | bool addErrorSuffix(const Twine &Suffix) { |
111 | return getParser().addErrorSuffix(Suffix); |
112 | } |
113 | |
114 | bool HasBracketExpressions() const { return BracketExpressionsSupported; } |
115 | |
116 | /// @} |
117 | }; |
118 | |
119 | } // end namespace llvm |
120 | |
121 | #endif // LLVM_MC_MCPARSER_MCASMPARSEREXTENSION_H |
1 | //===- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface ------*- C++ -*-===// |
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 | #ifndef LLVM_MC_MCPARSER_MCASMLEXER_H |
11 | #define LLVM_MC_MCPARSER_MCASMLEXER_H |
12 | |
13 | #include "llvm/ADT/APInt.h" |
14 | #include "llvm/ADT/ArrayRef.h" |
15 | #include "llvm/ADT/SmallVector.h" |
16 | #include "llvm/ADT/StringRef.h" |
17 | #include "llvm/Support/SMLoc.h" |
18 | #include <algorithm> |
19 | #include <cassert> |
20 | #include <cstddef> |
21 | #include <cstdint> |
22 | #include <string> |
23 | |
24 | namespace llvm { |
25 | |
26 | /// Target independent representation for an assembler token. |
27 | class AsmToken { |
28 | public: |
29 | enum TokenKind { |
30 | // Markers |
31 | Eof, Error, |
32 | |
33 | // String values. |
34 | Identifier, |
35 | String, |
36 | |
37 | // Integer values. |
38 | Integer, |
39 | BigNum, // larger than 64 bits |
40 | |
41 | // Real values. |
42 | Real, |
43 | |
44 | // Comments |
45 | Comment, |
46 | HashDirective, |
47 | // No-value. |
48 | EndOfStatement, |
49 | Colon, |
50 | Space, |
51 | Plus, Minus, Tilde, |
52 | Slash, // '/' |
53 | BackSlash, // '\' |
54 | LParen, RParen, LBrac, RBrac, LCurly, RCurly, |
55 | Star, Dot, Comma, Dollar, Equal, EqualEqual, |
56 | |
57 | Pipe, PipePipe, Caret, |
58 | Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, |
59 | Less, LessEqual, LessLess, LessGreater, |
60 | Greater, GreaterEqual, GreaterGreater, At, |
61 | |
62 | // MIPS unary expression operators such as %neg. |
63 | PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi, |
64 | PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo, |
65 | PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi, |
66 | PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi, |
67 | PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi, |
68 | PercentTprel_Lo |
69 | }; |
70 | |
71 | private: |
72 | TokenKind Kind; |
73 | |
74 | /// A reference to the entire token contents; this is always a pointer into |
75 | /// a memory buffer owned by the source manager. |
76 | StringRef Str; |
77 | |
78 | APInt IntVal; |
79 | |
80 | public: |
81 | AsmToken() = default; |
82 | AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) |
83 | : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {} |
84 | AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0) |
85 | : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {} |
86 | |
87 | TokenKind getKind() const { return Kind; } |
88 | bool is(TokenKind K) const { return Kind == K; } |
89 | bool isNot(TokenKind K) const { return Kind != K; } |
90 | |
91 | SMLoc getLoc() const; |
92 | SMLoc getEndLoc() const; |
93 | SMRange getLocRange() const; |
94 | |
95 | /// Get the contents of a string token (without quotes). |
96 | StringRef getStringContents() const { |
97 | assert(Kind == String && "This token isn't a string!")(static_cast <bool> (Kind == String && "This token isn't a string!" ) ? void (0) : __assert_fail ("Kind == String && \"This token isn't a string!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 97, __extension__ __PRETTY_FUNCTION__)); |
98 | return Str.slice(1, Str.size() - 1); |
99 | } |
100 | |
101 | /// Get the identifier string for the current token, which should be an |
102 | /// identifier or a string. This gets the portion of the string which should |
103 | /// be used as the identifier, e.g., it does not include the quotes on |
104 | /// strings. |
105 | StringRef getIdentifier() const { |
106 | if (Kind == Identifier) |
107 | return getString(); |
108 | return getStringContents(); |
109 | } |
110 | |
111 | /// Get the string for the current token, this includes all characters (for |
112 | /// example, the quotes on strings) in the token. |
113 | /// |
114 | /// The returned StringRef points into the source manager's memory buffer, and |
115 | /// is safe to store across calls to Lex(). |
116 | StringRef getString() const { return Str; } |
117 | |
118 | // FIXME: Don't compute this in advance, it makes every token larger, and is |
119 | // also not generally what we want (it is nicer for recovery etc. to lex 123br |
120 | // as a single token, then diagnose as an invalid number). |
121 | int64_t getIntVal() const { |
122 | assert(Kind == Integer && "This token isn't an integer!")(static_cast <bool> (Kind == Integer && "This token isn't an integer!" ) ? void (0) : __assert_fail ("Kind == Integer && \"This token isn't an integer!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 122, __extension__ __PRETTY_FUNCTION__)); |
123 | return IntVal.getZExtValue(); |
124 | } |
125 | |
126 | APInt getAPIntVal() const { |
127 | assert((Kind == Integer || Kind == BigNum) &&(static_cast <bool> ((Kind == Integer || Kind == BigNum ) && "This token isn't an integer!") ? void (0) : __assert_fail ("(Kind == Integer || Kind == BigNum) && \"This token isn't an integer!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 128, __extension__ __PRETTY_FUNCTION__)) |
128 | "This token isn't an integer!")(static_cast <bool> ((Kind == Integer || Kind == BigNum ) && "This token isn't an integer!") ? void (0) : __assert_fail ("(Kind == Integer || Kind == BigNum) && \"This token isn't an integer!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 128, __extension__ __PRETTY_FUNCTION__)); |
129 | return IntVal; |
130 | } |
131 | }; |
132 | |
133 | /// A callback class which is notified of each comment in an assembly file as |
134 | /// it is lexed. |
135 | class AsmCommentConsumer { |
136 | public: |
137 | virtual ~AsmCommentConsumer() = default; |
138 | |
139 | /// Callback function for when a comment is lexed. Loc is the start of the |
140 | /// comment text (excluding the comment-start marker). CommentText is the text |
141 | /// of the comment, excluding the comment start and end markers, and the |
142 | /// newline for single-line comments. |
143 | virtual void HandleComment(SMLoc Loc, StringRef CommentText) = 0; |
144 | }; |
145 | |
146 | |
147 | /// Generic assembler lexer interface, for use by target specific assembly |
148 | /// lexers. |
149 | class MCAsmLexer { |
150 | /// The current token, stored in the base class for faster access. |
151 | SmallVector<AsmToken, 1> CurTok; |
152 | |
153 | /// The location and description of the current error |
154 | SMLoc ErrLoc; |
155 | std::string Err; |
156 | |
157 | protected: // Can only create subclasses. |
158 | const char *TokStart = nullptr; |
159 | bool SkipSpace = true; |
160 | bool AllowAtInIdentifier; |
161 | bool IsAtStartOfStatement = true; |
162 | AsmCommentConsumer *CommentConsumer = nullptr; |
163 | |
164 | bool AltMacroMode; |
165 | MCAsmLexer(); |
166 | |
167 | virtual AsmToken LexToken() = 0; |
168 | |
169 | void SetError(SMLoc errLoc, const std::string &err) { |
170 | ErrLoc = errLoc; |
171 | Err = err; |
172 | } |
173 | |
174 | public: |
175 | MCAsmLexer(const MCAsmLexer &) = delete; |
176 | MCAsmLexer &operator=(const MCAsmLexer &) = delete; |
177 | virtual ~MCAsmLexer(); |
178 | |
179 | bool IsaAltMacroMode() { |
180 | return AltMacroMode; |
181 | } |
182 | |
183 | void SetAltMacroMode(bool AltMacroSet) { |
184 | AltMacroMode = AltMacroSet; |
185 | } |
186 | |
187 | /// Consume the next token from the input stream and return it. |
188 | /// |
189 | /// The lexer will continuosly return the end-of-file token once the end of |
190 | /// the main input file has been reached. |
191 | const AsmToken &Lex() { |
192 | assert(!CurTok.empty())(static_cast <bool> (!CurTok.empty()) ? void (0) : __assert_fail ("!CurTok.empty()", "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 192, __extension__ __PRETTY_FUNCTION__)); |
193 | // Mark if we parsing out a EndOfStatement. |
194 | IsAtStartOfStatement = CurTok.front().getKind() == AsmToken::EndOfStatement; |
195 | CurTok.erase(CurTok.begin()); |
196 | // LexToken may generate multiple tokens via UnLex but will always return |
197 | // the first one. Place returned value at head of CurTok vector. |
198 | if (CurTok.empty()) { |
199 | AsmToken T = LexToken(); |
200 | CurTok.insert(CurTok.begin(), T); |
201 | } |
202 | return CurTok.front(); |
203 | } |
204 | |
205 | void UnLex(AsmToken const &Token) { |
206 | IsAtStartOfStatement = false; |
207 | CurTok.insert(CurTok.begin(), Token); |
208 | } |
209 | |
210 | bool isAtStartOfStatement() { return IsAtStartOfStatement; } |
211 | |
212 | virtual StringRef LexUntilEndOfStatement() = 0; |
213 | |
214 | /// Get the current source location. |
215 | SMLoc getLoc() const; |
216 | |
217 | /// Get the current (last) lexed token. |
218 | const AsmToken &getTok() const { |
219 | return CurTok[0]; |
220 | } |
221 | |
222 | /// Look ahead at the next token to be lexed. |
223 | const AsmToken peekTok(bool ShouldSkipSpace = true) { |
224 | AsmToken Tok; |
225 | |
226 | MutableArrayRef<AsmToken> Buf(Tok); |
227 | size_t ReadCount = peekTokens(Buf, ShouldSkipSpace); |
228 | |
229 | assert(ReadCount == 1)(static_cast <bool> (ReadCount == 1) ? void (0) : __assert_fail ("ReadCount == 1", "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/MC/MCParser/MCAsmLexer.h" , 229, __extension__ __PRETTY_FUNCTION__)); |
230 | (void)ReadCount; |
231 | |
232 | return Tok; |
233 | } |
234 | |
235 | /// Look ahead an arbitrary number of tokens. |
236 | virtual size_t peekTokens(MutableArrayRef<AsmToken> Buf, |
237 | bool ShouldSkipSpace = true) = 0; |
238 | |
239 | /// Get the current error location |
240 | SMLoc getErrLoc() { |
241 | return ErrLoc; |
242 | } |
243 | |
244 | /// Get the current error string |
245 | const std::string &getErr() { |
246 | return Err; |
247 | } |
248 | |
249 | /// Get the kind of current token. |
250 | AsmToken::TokenKind getKind() const { return getTok().getKind(); } |
251 | |
252 | /// Check if the current token has kind \p K. |
253 | bool is(AsmToken::TokenKind K) const { return getTok().is(K); } |
254 | |
255 | /// Check if the current token has kind \p K. |
256 | bool isNot(AsmToken::TokenKind K) const { return getTok().isNot(K); } |
257 | |
258 | /// Set whether spaces should be ignored by the lexer |
259 | void setSkipSpace(bool val) { SkipSpace = val; } |
260 | |
261 | bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } |
262 | void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; } |
263 | |
264 | void setCommentConsumer(AsmCommentConsumer *CommentConsumer) { |
265 | this->CommentConsumer = CommentConsumer; |
266 | } |
267 | }; |
268 | |
269 | } // end namespace llvm |
270 | |
271 | #endif // LLVM_MC_MCPARSER_MCASMLEXER_H |
1 | //===- Twine.h - Fast Temporary String Concatenation ------------*- C++ -*-===// |
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 | #ifndef LLVM_ADT_TWINE_H |
11 | #define LLVM_ADT_TWINE_H |
12 | |
13 | #include "llvm/ADT/SmallVector.h" |
14 | #include "llvm/ADT/StringRef.h" |
15 | #include "llvm/Support/ErrorHandling.h" |
16 | #include <cassert> |
17 | #include <cstdint> |
18 | #include <string> |
19 | |
20 | namespace llvm { |
21 | |
22 | class formatv_object_base; |
23 | class raw_ostream; |
24 | |
25 | /// Twine - A lightweight data structure for efficiently representing the |
26 | /// concatenation of temporary values as strings. |
27 | /// |
28 | /// A Twine is a kind of rope, it represents a concatenated string using a |
29 | /// binary-tree, where the string is the preorder of the nodes. Since the |
30 | /// Twine can be efficiently rendered into a buffer when its result is used, |
31 | /// it avoids the cost of generating temporary values for intermediate string |
32 | /// results -- particularly in cases when the Twine result is never |
33 | /// required. By explicitly tracking the type of leaf nodes, we can also avoid |
34 | /// the creation of temporary strings for conversions operations (such as |
35 | /// appending an integer to a string). |
36 | /// |
37 | /// A Twine is not intended for use directly and should not be stored, its |
38 | /// implementation relies on the ability to store pointers to temporary stack |
39 | /// objects which may be deallocated at the end of a statement. Twines should |
40 | /// only be used accepted as const references in arguments, when an API wishes |
41 | /// to accept possibly-concatenated strings. |
42 | /// |
43 | /// Twines support a special 'null' value, which always concatenates to form |
44 | /// itself, and renders as an empty string. This can be returned from APIs to |
45 | /// effectively nullify any concatenations performed on the result. |
46 | /// |
47 | /// \b Implementation |
48 | /// |
49 | /// Given the nature of a Twine, it is not possible for the Twine's |
50 | /// concatenation method to construct interior nodes; the result must be |
51 | /// represented inside the returned value. For this reason a Twine object |
52 | /// actually holds two values, the left- and right-hand sides of a |
53 | /// concatenation. We also have nullary Twine objects, which are effectively |
54 | /// sentinel values that represent empty strings. |
55 | /// |
56 | /// Thus, a Twine can effectively have zero, one, or two children. The \see |
57 | /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for |
58 | /// testing the number of children. |
59 | /// |
60 | /// We maintain a number of invariants on Twine objects (FIXME: Why): |
61 | /// - Nullary twines are always represented with their Kind on the left-hand |
62 | /// side, and the Empty kind on the right-hand side. |
63 | /// - Unary twines are always represented with the value on the left-hand |
64 | /// side, and the Empty kind on the right-hand side. |
65 | /// - If a Twine has another Twine as a child, that child should always be |
66 | /// binary (otherwise it could have been folded into the parent). |
67 | /// |
68 | /// These invariants are check by \see isValid(). |
69 | /// |
70 | /// \b Efficiency Considerations |
71 | /// |
72 | /// The Twine is designed to yield efficient and small code for common |
73 | /// situations. For this reason, the concat() method is inlined so that |
74 | /// concatenations of leaf nodes can be optimized into stores directly into a |
75 | /// single stack allocated object. |
76 | /// |
77 | /// In practice, not all compilers can be trusted to optimize concat() fully, |
78 | /// so we provide two additional methods (and accompanying operator+ |
79 | /// overloads) to guarantee that particularly important cases (cstring plus |
80 | /// StringRef) codegen as desired. |
81 | class Twine { |
82 | /// NodeKind - Represent the type of an argument. |
83 | enum NodeKind : unsigned char { |
84 | /// An empty string; the result of concatenating anything with it is also |
85 | /// empty. |
86 | NullKind, |
87 | |
88 | /// The empty string. |
89 | EmptyKind, |
90 | |
91 | /// A pointer to a Twine instance. |
92 | TwineKind, |
93 | |
94 | /// A pointer to a C string instance. |
95 | CStringKind, |
96 | |
97 | /// A pointer to an std::string instance. |
98 | StdStringKind, |
99 | |
100 | /// A pointer to a StringRef instance. |
101 | StringRefKind, |
102 | |
103 | /// A pointer to a SmallString instance. |
104 | SmallStringKind, |
105 | |
106 | /// A pointer to a formatv_object_base instance. |
107 | FormatvObjectKind, |
108 | |
109 | /// A char value, to render as a character. |
110 | CharKind, |
111 | |
112 | /// An unsigned int value, to render as an unsigned decimal integer. |
113 | DecUIKind, |
114 | |
115 | /// An int value, to render as a signed decimal integer. |
116 | DecIKind, |
117 | |
118 | /// A pointer to an unsigned long value, to render as an unsigned decimal |
119 | /// integer. |
120 | DecULKind, |
121 | |
122 | /// A pointer to a long value, to render as a signed decimal integer. |
123 | DecLKind, |
124 | |
125 | /// A pointer to an unsigned long long value, to render as an unsigned |
126 | /// decimal integer. |
127 | DecULLKind, |
128 | |
129 | /// A pointer to a long long value, to render as a signed decimal integer. |
130 | DecLLKind, |
131 | |
132 | /// A pointer to a uint64_t value, to render as an unsigned hexadecimal |
133 | /// integer. |
134 | UHexKind |
135 | }; |
136 | |
137 | union Child |
138 | { |
139 | const Twine *twine; |
140 | const char *cString; |
141 | const std::string *stdString; |
142 | const StringRef *stringRef; |
143 | const SmallVectorImpl<char> *smallString; |
144 | const formatv_object_base *formatvObject; |
145 | char character; |
146 | unsigned int decUI; |
147 | int decI; |
148 | const unsigned long *decUL; |
149 | const long *decL; |
150 | const unsigned long long *decULL; |
151 | const long long *decLL; |
152 | const uint64_t *uHex; |
153 | }; |
154 | |
155 | /// LHS - The prefix in the concatenation, which may be uninitialized for |
156 | /// Null or Empty kinds. |
157 | Child LHS; |
158 | |
159 | /// RHS - The suffix in the concatenation, which may be uninitialized for |
160 | /// Null or Empty kinds. |
161 | Child RHS; |
162 | |
163 | /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). |
164 | NodeKind LHSKind = EmptyKind; |
165 | |
166 | /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). |
167 | NodeKind RHSKind = EmptyKind; |
168 | |
169 | /// Construct a nullary twine; the kind must be NullKind or EmptyKind. |
170 | explicit Twine(NodeKind Kind) : LHSKind(Kind) { |
171 | assert(isNullary() && "Invalid kind!")(static_cast <bool> (isNullary() && "Invalid kind!" ) ? void (0) : __assert_fail ("isNullary() && \"Invalid kind!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 171, __extension__ __PRETTY_FUNCTION__)); |
172 | } |
173 | |
174 | /// Construct a binary twine. |
175 | explicit Twine(const Twine &LHS, const Twine &RHS) |
176 | : LHSKind(TwineKind), RHSKind(TwineKind) { |
177 | this->LHS.twine = &LHS; |
178 | this->RHS.twine = &RHS; |
179 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 179, __extension__ __PRETTY_FUNCTION__)); |
180 | } |
181 | |
182 | /// Construct a twine from explicit values. |
183 | explicit Twine(Child LHS, NodeKind LHSKind, Child RHS, NodeKind RHSKind) |
184 | : LHS(LHS), RHS(RHS), LHSKind(LHSKind), RHSKind(RHSKind) { |
185 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 185, __extension__ __PRETTY_FUNCTION__)); |
186 | } |
187 | |
188 | /// Check for the null twine. |
189 | bool isNull() const { |
190 | return getLHSKind() == NullKind; |
191 | } |
192 | |
193 | /// Check for the empty twine. |
194 | bool isEmpty() const { |
195 | return getLHSKind() == EmptyKind; |
196 | } |
197 | |
198 | /// Check if this is a nullary twine (null or empty). |
199 | bool isNullary() const { |
200 | return isNull() || isEmpty(); |
201 | } |
202 | |
203 | /// Check if this is a unary twine. |
204 | bool isUnary() const { |
205 | return getRHSKind() == EmptyKind && !isNullary(); |
206 | } |
207 | |
208 | /// Check if this is a binary twine. |
209 | bool isBinary() const { |
210 | return getLHSKind() != NullKind && getRHSKind() != EmptyKind; |
211 | } |
212 | |
213 | /// Check if this is a valid twine (satisfying the invariants on |
214 | /// order and number of arguments). |
215 | bool isValid() const { |
216 | // Nullary twines always have Empty on the RHS. |
217 | if (isNullary() && getRHSKind() != EmptyKind) |
218 | return false; |
219 | |
220 | // Null should never appear on the RHS. |
221 | if (getRHSKind() == NullKind) |
222 | return false; |
223 | |
224 | // The RHS cannot be non-empty if the LHS is empty. |
225 | if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) |
226 | return false; |
227 | |
228 | // A twine child should always be binary. |
229 | if (getLHSKind() == TwineKind && |
230 | !LHS.twine->isBinary()) |
231 | return false; |
232 | if (getRHSKind() == TwineKind && |
233 | !RHS.twine->isBinary()) |
234 | return false; |
235 | |
236 | return true; |
237 | } |
238 | |
239 | /// Get the NodeKind of the left-hand side. |
240 | NodeKind getLHSKind() const { return LHSKind; } |
241 | |
242 | /// Get the NodeKind of the right-hand side. |
243 | NodeKind getRHSKind() const { return RHSKind; } |
244 | |
245 | /// Print one child from a twine. |
246 | void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; |
247 | |
248 | /// Print the representation of one child from a twine. |
249 | void printOneChildRepr(raw_ostream &OS, Child Ptr, |
250 | NodeKind Kind) const; |
251 | |
252 | public: |
253 | /// @name Constructors |
254 | /// @{ |
255 | |
256 | /// Construct from an empty string. |
257 | /*implicit*/ Twine() { |
258 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 258, __extension__ __PRETTY_FUNCTION__)); |
259 | } |
260 | |
261 | Twine(const Twine &) = default; |
262 | |
263 | /// Construct from a C string. |
264 | /// |
265 | /// We take care here to optimize "" into the empty twine -- this will be |
266 | /// optimized out for string constants. This allows Twine arguments have |
267 | /// default "" values, without introducing unnecessary string constants. |
268 | /*implicit*/ Twine(const char *Str) { |
269 | if (Str[0] != '\0') { |
270 | LHS.cString = Str; |
271 | LHSKind = CStringKind; |
272 | } else |
273 | LHSKind = EmptyKind; |
274 | |
275 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 275, __extension__ __PRETTY_FUNCTION__)); |
276 | } |
277 | |
278 | /// Construct from an std::string. |
279 | /*implicit*/ Twine(const std::string &Str) : LHSKind(StdStringKind) { |
280 | LHS.stdString = &Str; |
281 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 281, __extension__ __PRETTY_FUNCTION__)); |
282 | } |
283 | |
284 | /// Construct from a StringRef. |
285 | /*implicit*/ Twine(const StringRef &Str) : LHSKind(StringRefKind) { |
286 | LHS.stringRef = &Str; |
287 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 287, __extension__ __PRETTY_FUNCTION__)); |
288 | } |
289 | |
290 | /// Construct from a SmallString. |
291 | /*implicit*/ Twine(const SmallVectorImpl<char> &Str) |
292 | : LHSKind(SmallStringKind) { |
293 | LHS.smallString = &Str; |
294 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 294, __extension__ __PRETTY_FUNCTION__)); |
295 | } |
296 | |
297 | /// Construct from a formatv_object_base. |
298 | /*implicit*/ Twine(const formatv_object_base &Fmt) |
299 | : LHSKind(FormatvObjectKind) { |
300 | LHS.formatvObject = &Fmt; |
301 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 301, __extension__ __PRETTY_FUNCTION__)); |
302 | } |
303 | |
304 | /// Construct from a char. |
305 | explicit Twine(char Val) : LHSKind(CharKind) { |
306 | LHS.character = Val; |
307 | } |
308 | |
309 | /// Construct from a signed char. |
310 | explicit Twine(signed char Val) : LHSKind(CharKind) { |
311 | LHS.character = static_cast<char>(Val); |
312 | } |
313 | |
314 | /// Construct from an unsigned char. |
315 | explicit Twine(unsigned char Val) : LHSKind(CharKind) { |
316 | LHS.character = static_cast<char>(Val); |
317 | } |
318 | |
319 | /// Construct a twine to print \p Val as an unsigned decimal integer. |
320 | explicit Twine(unsigned Val) : LHSKind(DecUIKind) { |
321 | LHS.decUI = Val; |
322 | } |
323 | |
324 | /// Construct a twine to print \p Val as a signed decimal integer. |
325 | explicit Twine(int Val) : LHSKind(DecIKind) { |
326 | LHS.decI = Val; |
327 | } |
328 | |
329 | /// Construct a twine to print \p Val as an unsigned decimal integer. |
330 | explicit Twine(const unsigned long &Val) : LHSKind(DecULKind) { |
331 | LHS.decUL = &Val; |
332 | } |
333 | |
334 | /// Construct a twine to print \p Val as a signed decimal integer. |
335 | explicit Twine(const long &Val) : LHSKind(DecLKind) { |
336 | LHS.decL = &Val; |
337 | } |
338 | |
339 | /// Construct a twine to print \p Val as an unsigned decimal integer. |
340 | explicit Twine(const unsigned long long &Val) : LHSKind(DecULLKind) { |
341 | LHS.decULL = &Val; |
342 | } |
343 | |
344 | /// Construct a twine to print \p Val as a signed decimal integer. |
345 | explicit Twine(const long long &Val) : LHSKind(DecLLKind) { |
346 | LHS.decLL = &Val; |
347 | } |
348 | |
349 | // FIXME: Unfortunately, to make sure this is as efficient as possible we |
350 | // need extra binary constructors from particular types. We can't rely on |
351 | // the compiler to be smart enough to fold operator+()/concat() down to the |
352 | // right thing. Yet. |
353 | |
354 | /// Construct as the concatenation of a C string and a StringRef. |
355 | /*implicit*/ Twine(const char *LHS, const StringRef &RHS) |
356 | : LHSKind(CStringKind), RHSKind(StringRefKind) { |
357 | this->LHS.cString = LHS; |
358 | this->RHS.stringRef = &RHS; |
359 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 359, __extension__ __PRETTY_FUNCTION__)); |
360 | } |
361 | |
362 | /// Construct as the concatenation of a StringRef and a C string. |
363 | /*implicit*/ Twine(const StringRef &LHS, const char *RHS) |
364 | : LHSKind(StringRefKind), RHSKind(CStringKind) { |
365 | this->LHS.stringRef = &LHS; |
366 | this->RHS.cString = RHS; |
367 | assert(isValid() && "Invalid twine!")(static_cast <bool> (isValid() && "Invalid twine!" ) ? void (0) : __assert_fail ("isValid() && \"Invalid twine!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 367, __extension__ __PRETTY_FUNCTION__)); |
368 | } |
369 | |
370 | /// Since the intended use of twines is as temporary objects, assignments |
371 | /// when concatenating might cause undefined behavior or stack corruptions |
372 | Twine &operator=(const Twine &) = delete; |
373 | |
374 | /// Create a 'null' string, which is an empty string that always |
375 | /// concatenates to form another empty string. |
376 | static Twine createNull() { |
377 | return Twine(NullKind); |
378 | } |
379 | |
380 | /// @} |
381 | /// @name Numeric Conversions |
382 | /// @{ |
383 | |
384 | // Construct a twine to print \p Val as an unsigned hexadecimal integer. |
385 | static Twine utohexstr(const uint64_t &Val) { |
386 | Child LHS, RHS; |
387 | LHS.uHex = &Val; |
388 | RHS.twine = nullptr; |
389 | return Twine(LHS, UHexKind, RHS, EmptyKind); |
390 | } |
391 | |
392 | /// @} |
393 | /// @name Predicate Operations |
394 | /// @{ |
395 | |
396 | /// Check if this twine is trivially empty; a false return value does not |
397 | /// necessarily mean the twine is empty. |
398 | bool isTriviallyEmpty() const { |
399 | return isNullary(); |
400 | } |
401 | |
402 | /// Return true if this twine can be dynamically accessed as a single |
403 | /// StringRef value with getSingleStringRef(). |
404 | bool isSingleStringRef() const { |
405 | if (getRHSKind() != EmptyKind) return false; |
406 | |
407 | switch (getLHSKind()) { |
408 | case EmptyKind: |
409 | case CStringKind: |
410 | case StdStringKind: |
411 | case StringRefKind: |
412 | case SmallStringKind: |
413 | return true; |
414 | default: |
415 | return false; |
416 | } |
417 | } |
418 | |
419 | /// @} |
420 | /// @name String Operations |
421 | /// @{ |
422 | |
423 | Twine concat(const Twine &Suffix) const; |
424 | |
425 | /// @} |
426 | /// @name Output & Conversion. |
427 | /// @{ |
428 | |
429 | /// Return the twine contents as a std::string. |
430 | std::string str() const; |
431 | |
432 | /// Append the concatenated string into the given SmallString or SmallVector. |
433 | void toVector(SmallVectorImpl<char> &Out) const; |
434 | |
435 | /// This returns the twine as a single StringRef. This method is only valid |
436 | /// if isSingleStringRef() is true. |
437 | StringRef getSingleStringRef() const { |
438 | assert(isSingleStringRef() &&"This cannot be had as a single stringref!")(static_cast <bool> (isSingleStringRef() &&"This cannot be had as a single stringref!" ) ? void (0) : __assert_fail ("isSingleStringRef() &&\"This cannot be had as a single stringref!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 438, __extension__ __PRETTY_FUNCTION__)); |
439 | switch (getLHSKind()) { |
440 | default: llvm_unreachable("Out of sync with isSingleStringRef")::llvm::llvm_unreachable_internal("Out of sync with isSingleStringRef" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/Twine.h" , 440); |
441 | case EmptyKind: return StringRef(); |
442 | case CStringKind: return StringRef(LHS.cString); |
443 | case StdStringKind: return StringRef(*LHS.stdString); |
444 | case StringRefKind: return *LHS.stringRef; |
445 | case SmallStringKind: |
446 | return StringRef(LHS.smallString->data(), LHS.smallString->size()); |
447 | } |
448 | } |
449 | |
450 | /// This returns the twine as a single StringRef if it can be |
451 | /// represented as such. Otherwise the twine is written into the given |
452 | /// SmallVector and a StringRef to the SmallVector's data is returned. |
453 | StringRef toStringRef(SmallVectorImpl<char> &Out) const { |
454 | if (isSingleStringRef()) |
455 | return getSingleStringRef(); |
456 | toVector(Out); |
457 | return StringRef(Out.data(), Out.size()); |
458 | } |
459 | |
460 | /// This returns the twine as a single null terminated StringRef if it |
461 | /// can be represented as such. Otherwise the twine is written into the |
462 | /// given SmallVector and a StringRef to the SmallVector's data is returned. |
463 | /// |
464 | /// The returned StringRef's size does not include the null terminator. |
465 | StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const; |
466 | |
467 | /// Write the concatenated string represented by this twine to the |
468 | /// stream \p OS. |
469 | void print(raw_ostream &OS) const; |
470 | |
471 | /// Dump the concatenated string represented by this twine to stderr. |
472 | void dump() const; |
473 | |
474 | /// Write the representation of this twine to the stream \p OS. |
475 | void printRepr(raw_ostream &OS) const; |
476 | |
477 | /// Dump the representation of this twine to stderr. |
478 | void dumpRepr() const; |
479 | |
480 | /// @} |
481 | }; |
482 | |
483 | /// @name Twine Inline Implementations |
484 | /// @{ |
485 | |
486 | inline Twine Twine::concat(const Twine &Suffix) const { |
487 | // Concatenation with null is null. |
488 | if (isNull() || Suffix.isNull()) |
489 | return Twine(NullKind); |
490 | |
491 | // Concatenation with empty yields the other side. |
492 | if (isEmpty()) |
493 | return Suffix; |
494 | if (Suffix.isEmpty()) |
495 | return *this; |
496 | |
497 | // Otherwise we need to create a new node, taking care to fold in unary |
498 | // twines. |
499 | Child NewLHS, NewRHS; |
500 | NewLHS.twine = this; |
501 | NewRHS.twine = &Suffix; |
502 | NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; |
503 | if (isUnary()) { |
504 | NewLHS = LHS; |
505 | NewLHSKind = getLHSKind(); |
506 | } |
507 | if (Suffix.isUnary()) { |
508 | NewRHS = Suffix.LHS; |
509 | NewRHSKind = Suffix.getLHSKind(); |
510 | } |
511 | |
512 | return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); |
513 | } |
514 | |
515 | inline Twine operator+(const Twine &LHS, const Twine &RHS) { |
516 | return LHS.concat(RHS); |
517 | } |
518 | |
519 | /// Additional overload to guarantee simplified codegen; this is equivalent to |
520 | /// concat(). |
521 | |
522 | inline Twine operator+(const char *LHS, const StringRef &RHS) { |
523 | return Twine(LHS, RHS); |
524 | } |
525 | |
526 | /// Additional overload to guarantee simplified codegen; this is equivalent to |
527 | /// concat(). |
528 | |
529 | inline Twine operator+(const StringRef &LHS, const char *RHS) { |
530 | return Twine(LHS, RHS); |
531 | } |
532 | |
533 | inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { |
534 | RHS.print(OS); |
535 | return OS; |
536 | } |
537 | |
538 | /// @} |
539 | |
540 | } // end namespace llvm |
541 | |
542 | #endif // LLVM_ADT_TWINE_H |