/src/keystone/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- RISCVAsmParser.cpp - Parse RISCV assembly to MCInst instructions --===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "MCTargetDesc/RISCVAsmBackend.h" |
10 | | #include "MCTargetDesc/RISCVMCExpr.h" |
11 | | #include "MCTargetDesc/RISCVMCTargetDesc.h" |
12 | | #include "MCTargetDesc/RISCVTargetStreamer.h" |
13 | | #include "TargetInfo/RISCVTargetInfo.h" |
14 | | #include "Utils/RISCVBaseInfo.h" |
15 | | #include "Utils/RISCVMatInt.h" |
16 | | #include "llvm/ADT/STLExtras.h" |
17 | | #include "llvm/ADT/SmallVector.h" |
18 | | #include "llvm/ADT/StringSwitch.h" |
19 | | #include "llvm/MC/MCAssembler.h" |
20 | | #include "llvm/MC/MCContext.h" |
21 | | #include "llvm/MC/MCExpr.h" |
22 | | #include "llvm/MC/MCInst.h" |
23 | | #include "llvm/MC/MCInstBuilder.h" |
24 | | #include "llvm/MC/MCObjectFileInfo.h" |
25 | | #include "llvm/MC/MCParser/MCAsmLexer.h" |
26 | | #include "llvm/MC/MCParser/MCParsedAsmOperand.h" |
27 | | #include "llvm/MC/MCParser/MCTargetAsmParser.h" |
28 | | #include "llvm/MC/MCRegisterInfo.h" |
29 | | #include "llvm/MC/MCStreamer.h" |
30 | | #include "llvm/MC/MCSubtargetInfo.h" |
31 | | #include "llvm/Support/Casting.h" |
32 | | #include "llvm/Support/MathExtras.h" |
33 | | #include "llvm/Support/TargetRegistry.h" |
34 | | |
35 | | #include "llvm/MC/MCELFStreamer.h" |
36 | | #include "RISCVGenAsmMatcher.inc" |
37 | | #include <limits> |
38 | | |
39 | | using namespace llvm_ks; |
40 | | |
41 | | // Include the auto-generated portion of the compress emitter. |
42 | | #define GEN_COMPRESS_INSTR |
43 | | #include "RISCVGenCompressInstEmitter.inc" |
44 | | |
45 | | namespace llvm_ks{ |
46 | | struct RISCVOperand; |
47 | | unsigned int ErrCd = 0; |
48 | | class RISCVAsmParser : public MCTargetAsmParser { |
49 | | SmallVector<FeatureBitset, 4> FeatureBitStack; |
50 | | RISCVABI::ABI ABI; |
51 | | |
52 | 171k | SMLoc getLoc() const { return getParser().getTok().getLoc(); } |
53 | | |
54 | 84.7k | bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); } |
55 | 51.3k | bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); } |
56 | | |
57 | 0 | RISCVTargetStreamer &getTargetStreamer() { |
58 | 0 | MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); |
59 | 0 | return static_cast<RISCVTargetStreamer &>(TS); |
60 | 0 | } |
61 | | |
62 | | unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, |
63 | | unsigned Kind) override; |
64 | | |
65 | | bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, |
66 | | int64_t Lower, int64_t Upper, Twine Msg); |
67 | | |
68 | | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
69 | | OperandVector &Operands, MCStreamer &Out, |
70 | | uint64_t &ErrorInfo, |
71 | | bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) override; |
72 | | |
73 | | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, unsigned int &ErrorCode) override; |
74 | | |
75 | | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, |
76 | | SMLoc NameLoc, OperandVector &Operands, unsigned int &ErrorCode) override; |
77 | | |
78 | | bool ParseDirective(AsmToken DirectiveID) override; |
79 | | |
80 | | // Helper to actually emit an instruction to the MCStreamer. Also, when |
81 | | // possible, compression of the instruction is performed. |
82 | | void emitToStreamer(MCStreamer &S, MCInst &Inst); |
83 | | |
84 | | // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that |
85 | | // synthesize the desired immedate value into the destination register. |
86 | | void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out); |
87 | | |
88 | | // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement |
89 | | // helpers such as emitLoadLocalAddress and emitLoadAddress. |
90 | | void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, |
91 | | const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi, |
92 | | unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out); |
93 | | |
94 | | // Helper to emit pseudo instruction "lla" used in PC-rel addressing. |
95 | | void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); |
96 | | |
97 | | // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing. |
98 | | void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); |
99 | | |
100 | | // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS |
101 | | // addressing. |
102 | | void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); |
103 | | |
104 | | // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS |
105 | | // addressing. |
106 | | void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); |
107 | | |
108 | | // Helper to emit pseudo load/store instruction with a symbol. |
109 | | void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, |
110 | | MCStreamer &Out, bool HasTmpReg); |
111 | | |
112 | | // Checks that a PseudoAddTPRel is using x4/tp in its second input operand. |
113 | | // Enforcing this using a restricted register class for the second input |
114 | | // operand of PseudoAddTPRel results in a poor diagnostic due to the fact |
115 | | // 'add' is an overloaded mnemonic. |
116 | | bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands); |
117 | | |
118 | | /// Helper for processing MC instructions that have been successfully matched |
119 | | /// by MatchAndEmitInstruction. Modifications to the emitted instructions, |
120 | | /// like the expansion of pseudo instructions (e.g., "li"), can be performed |
121 | | /// in this method. |
122 | | bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, |
123 | | MCStreamer &Out); |
124 | | |
125 | | // Auto-generated instruction matching functions |
126 | | #define GET_ASSEMBLER_HEADER |
127 | | #include "RISCVGenAsmMatcher.inc" |
128 | | |
129 | | OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands); |
130 | | OperandMatchResultTy parseImmediate(OperandVector &Operands); |
131 | | OperandMatchResultTy parseRegister(OperandVector &Operands, |
132 | | bool AllowParens = false, unsigned int &ErrorCode = ErrCd); |
133 | | OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); |
134 | | OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); |
135 | | OperandMatchResultTy parseBareSymbol(OperandVector &Operands); |
136 | | OperandMatchResultTy parseCallSymbol(OperandVector &Operands); |
137 | | OperandMatchResultTy parseJALOffset(OperandVector &Operands); |
138 | | |
139 | | bool parseOperand(OperandVector &Operands, StringRef Mnemonic); |
140 | | |
141 | | bool parseDirectiveOption(); |
142 | | |
143 | 0 | void setFeatureBits(uint64_t Feature, StringRef FeatureString) { |
144 | 0 | if (!(getSTI().getFeatureBits()[Feature])) { |
145 | 0 | MCSubtargetInfo &STI = copySTI(); |
146 | 0 | setAvailableFeaturesFB( |
147 | 0 | ComputeAvailableFeaturesFB(STI.ToggleFeature(FeatureString))); |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { |
152 | 0 | if (getSTI().getFeatureBits()[Feature]) { |
153 | 0 | MCSubtargetInfo &STI = copySTI(); |
154 | 0 | setAvailableFeaturesFB( |
155 | 0 | ComputeAvailableFeaturesFB(STI.ToggleFeature(FeatureString))); |
156 | 0 | } |
157 | 0 | } |
158 | | |
159 | 0 | void pushFeatureBits() { |
160 | 0 | FeatureBitStack.push_back(getSTI().getFeatureBits()); |
161 | 0 | } |
162 | | |
163 | 0 | bool popFeatureBits() { |
164 | 0 | if (FeatureBitStack.empty()) |
165 | 0 | return true; |
166 | | |
167 | 0 | FeatureBitset FeatureBits = FeatureBitStack.pop_back_val(); |
168 | 0 | copySTI().setFeatureBits(FeatureBits); |
169 | 0 | setAvailableFeaturesFB(ComputeAvailableFeaturesFB(FeatureBits)); |
170 | |
|
171 | 0 | return false; |
172 | 0 | } |
173 | | |
174 | | public: |
175 | | enum RISCVMatchResultTy { |
176 | | Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, |
177 | | #define GET_OPERAND_DIAGNOSTIC_TYPES |
178 | | #include "RISCVGenAsmMatcher.inc" |
179 | | #undef GET_OPERAND_DIAGNOSTIC_TYPES |
180 | | }; |
181 | | |
182 | | static bool classifySymbolRef(const MCExpr *Expr, |
183 | | RISCVMCExpr::VariantKind &Kind, |
184 | | int64_t &Addend); |
185 | | |
186 | | RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, |
187 | | const MCInstrInfo &MII, const MCTargetOptions &Options) |
188 | 21.8k | : MCTargetAsmParser(Options, STI) { |
189 | 21.8k | Parser.addAliasForDirective(".half", ".2byte"); |
190 | 21.8k | Parser.addAliasForDirective(".hword", ".2byte"); |
191 | 21.8k | Parser.addAliasForDirective(".word", ".4byte"); |
192 | 21.8k | Parser.addAliasForDirective(".dword", ".8byte"); |
193 | 21.8k | setAvailableFeaturesFB(ComputeAvailableFeaturesFB(STI.getFeatureBits())); |
194 | 21.8k | } |
195 | | }; |
196 | | |
197 | | /// RISCVOperand - Instances of this class represent a parsed machine |
198 | | /// instruction |
199 | | struct RISCVOperand : public MCParsedAsmOperand { |
200 | | |
201 | | enum KindTy { |
202 | | Token, |
203 | | Register, |
204 | | Immediate, |
205 | | SystemRegister |
206 | | } Kind; |
207 | | |
208 | | bool IsRV64; |
209 | | |
210 | | struct RegOp { |
211 | | unsigned RegNum; |
212 | | }; |
213 | | |
214 | | struct ImmOp { |
215 | | const MCExpr *Val; |
216 | | }; |
217 | | |
218 | | struct SysRegOp { |
219 | | const char *Data; |
220 | | unsigned Length; |
221 | | unsigned Encoding; |
222 | | // FIXME: Add the Encoding parsed fields as needed for checks, |
223 | | // e.g.: read/write or user/supervisor/machine privileges. |
224 | | }; |
225 | | |
226 | | SMLoc StartLoc, EndLoc; |
227 | | union { |
228 | | StringRef Tok; |
229 | | RegOp Reg; |
230 | | ImmOp Imm; |
231 | | struct SysRegOp SysReg; |
232 | | }; |
233 | | |
234 | 84.7k | RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} |
235 | | |
236 | | public: |
237 | 0 | RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() { |
238 | 0 | Kind = o.Kind; |
239 | 0 | IsRV64 = o.IsRV64; |
240 | 0 | StartLoc = o.StartLoc; |
241 | 0 | EndLoc = o.EndLoc; |
242 | 0 | switch (Kind) { |
243 | 0 | case Register: |
244 | 0 | Reg = o.Reg; |
245 | 0 | break; |
246 | 0 | case Immediate: |
247 | 0 | Imm = o.Imm; |
248 | 0 | break; |
249 | 0 | case Token: |
250 | 0 | Tok = o.Tok; |
251 | 0 | break; |
252 | 0 | case SystemRegister: |
253 | 0 | SysReg = o.SysReg; |
254 | 0 | break; |
255 | 0 | } |
256 | 0 | } |
257 | | |
258 | 1.12k | bool isToken() const override { return Kind == Token; } |
259 | 654 | bool isReg() const override { return Kind == Register; } |
260 | 819 | bool isImm() const override { return Kind == Immediate; } |
261 | 0 | bool isMem() const override { return false; } |
262 | 12 | bool isSystemRegister() const { return Kind == SystemRegister; } |
263 | | |
264 | | static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, |
265 | 1.48k | RISCVMCExpr::VariantKind &VK) { |
266 | 1.48k | if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) { |
267 | 70 | VK = RE->getKind(); |
268 | 70 | return RE->evaluateAsConstant(Imm); |
269 | 70 | } |
270 | | |
271 | 1.41k | if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { |
272 | 1.27k | VK = RISCVMCExpr::VK_RISCV_None; |
273 | 1.27k | Imm = CE->getValue(); |
274 | 1.27k | return true; |
275 | 1.27k | } |
276 | | |
277 | 144 | return false; |
278 | 1.41k | } |
279 | | |
280 | | // True if operand is a symbol with no modifiers, or a constant with no |
281 | | // modifiers and isShiftedInt<N-1, 1>(Op). |
282 | 743 | template <int N> bool isBareSimmNLsb0() const { |
283 | 743 | int64_t Imm; |
284 | 743 | RISCVMCExpr::VariantKind VK; |
285 | 743 | if (!isImm()) |
286 | 0 | return false; |
287 | 743 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
288 | 743 | bool IsValid; |
289 | 743 | if (!IsConstantImm) |
290 | 76 | IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); |
291 | 667 | else |
292 | 667 | IsValid = isShiftedInt<N - 1, 1>(Imm); |
293 | 743 | return IsValid && VK == RISCVMCExpr::VK_RISCV_None; |
294 | 743 | } bool llvm_ks::RISCVOperand::isBareSimmNLsb0<21>() const Line | Count | Source | 282 | 743 | template <int N> bool isBareSimmNLsb0() const { | 283 | 743 | int64_t Imm; | 284 | 743 | RISCVMCExpr::VariantKind VK; | 285 | 743 | if (!isImm()) | 286 | 0 | return false; | 287 | 743 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); | 288 | 743 | bool IsValid; | 289 | 743 | if (!IsConstantImm) | 290 | 76 | IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); | 291 | 667 | else | 292 | 667 | IsValid = isShiftedInt<N - 1, 1>(Imm); | 293 | 743 | return IsValid && VK == RISCVMCExpr::VK_RISCV_None; | 294 | 743 | } |
Unexecuted instantiation: bool llvm_ks::RISCVOperand::isBareSimmNLsb0<13>() const Unexecuted instantiation: bool llvm_ks::RISCVOperand::isBareSimmNLsb0<9>() const Unexecuted instantiation: bool llvm_ks::RISCVOperand::isBareSimmNLsb0<12>() const |
295 | | |
296 | | // Predicate methods for AsmOperands defined in RISCVInstrInfo.td |
297 | | |
298 | 0 | bool isBareSymbol() const { |
299 | 0 | int64_t Imm; |
300 | 0 | RISCVMCExpr::VariantKind VK; |
301 | | // Must be of 'immediate' type but not a constant. |
302 | 0 | if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) |
303 | 0 | return false; |
304 | 0 | return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && |
305 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
306 | 0 | } |
307 | | |
308 | 50 | bool isCallSymbol() const { |
309 | 50 | int64_t Imm; |
310 | 50 | RISCVMCExpr::VariantKind VK; |
311 | | // Must be of 'immediate' type but not a constant. |
312 | 50 | if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) |
313 | 2 | return false; |
314 | 48 | return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && |
315 | 48 | (VK == RISCVMCExpr::VK_RISCV_CALL || |
316 | 43 | VK == RISCVMCExpr::VK_RISCV_CALL_PLT); |
317 | 50 | } |
318 | | |
319 | 0 | bool isTPRelAddSymbol() const { |
320 | 0 | int64_t Imm; |
321 | 0 | RISCVMCExpr::VariantKind VK; |
322 | | // Must be of 'immediate' type but not a constant. |
323 | 0 | if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) |
324 | 0 | return false; |
325 | 0 | return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && |
326 | 0 | VK == RISCVMCExpr::VK_RISCV_TPREL_ADD; |
327 | 0 | } |
328 | | |
329 | 12 | bool isCSRSystemRegister() const { return isSystemRegister(); } |
330 | | |
331 | | /// Return true if the operand is a valid for the fence instruction e.g. |
332 | | /// ('iorw'). |
333 | 1 | bool isFenceArg() const { |
334 | 1 | if (!isImm()) |
335 | 0 | return false; |
336 | 1 | const MCExpr *Val = getImm(); |
337 | 1 | auto *SVal = dyn_cast<MCSymbolRefExpr>(Val); |
338 | 1 | if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) |
339 | 1 | return false; |
340 | | |
341 | 0 | StringRef Str = SVal->getSymbol().getName(); |
342 | | // Letters must be unique, taken from 'iorw', and in ascending order. This |
343 | | // holds as long as each individual character is one of 'iorw' and is |
344 | | // greater than the previous character. |
345 | 0 | char Prev = '\0'; |
346 | 0 | for (char c : Str) { |
347 | 0 | if (c != 'i' && c != 'o' && c != 'r' && c != 'w') |
348 | 0 | return false; |
349 | 0 | if (c <= Prev) |
350 | 0 | return false; |
351 | 0 | Prev = c; |
352 | 0 | } |
353 | 0 | return true; |
354 | 0 | } |
355 | | |
356 | | /// Return true if the operand is a valid floating point rounding mode. |
357 | 0 | bool isFRMArg() const { |
358 | 0 | if (!isImm()) |
359 | 0 | return false; |
360 | 0 | const MCExpr *Val = getImm(); |
361 | 0 | auto *SVal = dyn_cast<MCSymbolRefExpr>(Val); |
362 | 0 | if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) |
363 | 0 | return false; |
364 | | |
365 | 0 | StringRef Str = SVal->getSymbol().getName(); |
366 | |
|
367 | 0 | return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid; |
368 | 0 | } |
369 | | |
370 | 0 | bool isImmXLenLI() const { |
371 | 0 | int64_t Imm; |
372 | 0 | RISCVMCExpr::VariantKind VK; |
373 | 0 | if (!isImm()) |
374 | 0 | return false; |
375 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
376 | 0 | if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO) |
377 | 0 | return true; |
378 | | // Given only Imm, ensuring that the actually specified constant is either |
379 | | // a signed or unsigned 64-bit number is unfortunately impossible. |
380 | 0 | bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm); |
381 | 0 | return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None; |
382 | 0 | } |
383 | | |
384 | 0 | bool isUImmLog2XLen() const { |
385 | 0 | int64_t Imm; |
386 | 0 | RISCVMCExpr::VariantKind VK; |
387 | 0 | if (!isImm()) |
388 | 0 | return false; |
389 | 0 | if (!evaluateConstantImm(getImm(), Imm, VK) || |
390 | 0 | VK != RISCVMCExpr::VK_RISCV_None) |
391 | 0 | return false; |
392 | 0 | return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); |
393 | 0 | } |
394 | | |
395 | 0 | bool isUImmLog2XLenNonZero() const { |
396 | 0 | int64_t Imm; |
397 | 0 | RISCVMCExpr::VariantKind VK; |
398 | 0 | if (!isImm()) |
399 | 0 | return false; |
400 | 0 | if (!evaluateConstantImm(getImm(), Imm, VK) || |
401 | 0 | VK != RISCVMCExpr::VK_RISCV_None) |
402 | 0 | return false; |
403 | 0 | if (Imm == 0) |
404 | 0 | return false; |
405 | 0 | return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); |
406 | 0 | } |
407 | | |
408 | 4 | bool isUImm5() const { |
409 | 4 | int64_t Imm; |
410 | 4 | RISCVMCExpr::VariantKind VK; |
411 | 4 | if (!isImm()) |
412 | 0 | return false; |
413 | 4 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
414 | 4 | return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; |
415 | 4 | } |
416 | | |
417 | 0 | bool isUImm5NonZero() const { |
418 | 0 | int64_t Imm; |
419 | 0 | RISCVMCExpr::VariantKind VK; |
420 | 0 | if (!isImm()) |
421 | 0 | return false; |
422 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
423 | 0 | return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) && |
424 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
425 | 0 | } |
426 | | |
427 | 0 | bool isSImm6() const { |
428 | 0 | if (!isImm()) |
429 | 0 | return false; |
430 | 0 | RISCVMCExpr::VariantKind VK; |
431 | 0 | int64_t Imm; |
432 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
433 | 0 | return IsConstantImm && isInt<6>(Imm) && |
434 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
435 | 0 | } |
436 | | |
437 | 0 | bool isSImm6NonZero() const { |
438 | 0 | if (!isImm()) |
439 | 0 | return false; |
440 | 0 | RISCVMCExpr::VariantKind VK; |
441 | 0 | int64_t Imm; |
442 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
443 | 0 | return IsConstantImm && isInt<6>(Imm) && (Imm != 0) && |
444 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
445 | 0 | } |
446 | | |
447 | 0 | bool isCLUIImm() const { |
448 | 0 | if (!isImm()) |
449 | 0 | return false; |
450 | 0 | int64_t Imm; |
451 | 0 | RISCVMCExpr::VariantKind VK; |
452 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
453 | 0 | return IsConstantImm && (Imm != 0) && |
454 | 0 | (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) && |
455 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
456 | 0 | } |
457 | | |
458 | 0 | bool isUImm7Lsb00() const { |
459 | 0 | if (!isImm()) |
460 | 0 | return false; |
461 | 0 | int64_t Imm; |
462 | 0 | RISCVMCExpr::VariantKind VK; |
463 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
464 | 0 | return IsConstantImm && isShiftedUInt<5, 2>(Imm) && |
465 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
466 | 0 | } |
467 | | |
468 | 0 | bool isUImm8Lsb00() const { |
469 | 0 | if (!isImm()) |
470 | 0 | return false; |
471 | 0 | int64_t Imm; |
472 | 0 | RISCVMCExpr::VariantKind VK; |
473 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
474 | 0 | return IsConstantImm && isShiftedUInt<6, 2>(Imm) && |
475 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
476 | 0 | } |
477 | | |
478 | 0 | bool isUImm8Lsb000() const { |
479 | 0 | if (!isImm()) |
480 | 0 | return false; |
481 | 0 | int64_t Imm; |
482 | 0 | RISCVMCExpr::VariantKind VK; |
483 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
484 | 0 | return IsConstantImm && isShiftedUInt<5, 3>(Imm) && |
485 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
486 | 0 | } |
487 | | |
488 | 0 | bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); } |
489 | | |
490 | 0 | bool isUImm9Lsb000() const { |
491 | 0 | if (!isImm()) |
492 | 0 | return false; |
493 | 0 | int64_t Imm; |
494 | 0 | RISCVMCExpr::VariantKind VK; |
495 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
496 | 0 | return IsConstantImm && isShiftedUInt<6, 3>(Imm) && |
497 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
498 | 0 | } |
499 | | |
500 | 0 | bool isUImm10Lsb00NonZero() const { |
501 | 0 | if (!isImm()) |
502 | 0 | return false; |
503 | 0 | int64_t Imm; |
504 | 0 | RISCVMCExpr::VariantKind VK; |
505 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
506 | 0 | return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) && |
507 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
508 | 0 | } |
509 | | |
510 | 21 | bool isSImm12() const { |
511 | 21 | RISCVMCExpr::VariantKind VK; |
512 | 21 | int64_t Imm; |
513 | 21 | bool IsValid; |
514 | 21 | if (!isImm()) |
515 | 1 | return false; |
516 | 20 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
517 | 20 | if (!IsConstantImm) |
518 | 4 | IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); |
519 | 16 | else |
520 | 16 | IsValid = isInt<12>(Imm); |
521 | 20 | return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) || |
522 | 5 | VK == RISCVMCExpr::VK_RISCV_LO || |
523 | 5 | VK == RISCVMCExpr::VK_RISCV_PCREL_LO || |
524 | 5 | VK == RISCVMCExpr::VK_RISCV_TPREL_LO); |
525 | 21 | } |
526 | | |
527 | 0 | bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } |
528 | | |
529 | 0 | bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } |
530 | | |
531 | 0 | bool isSImm10Lsb0000NonZero() const { |
532 | 0 | if (!isImm()) |
533 | 0 | return false; |
534 | 0 | int64_t Imm; |
535 | 0 | RISCVMCExpr::VariantKind VK; |
536 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
537 | 0 | return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) && |
538 | 0 | VK == RISCVMCExpr::VK_RISCV_None; |
539 | 0 | } |
540 | | |
541 | 0 | bool isUImm20LUI() const { |
542 | 0 | RISCVMCExpr::VariantKind VK; |
543 | 0 | int64_t Imm; |
544 | 0 | bool IsValid; |
545 | 0 | if (!isImm()) |
546 | 0 | return false; |
547 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
548 | 0 | if (!IsConstantImm) { |
549 | 0 | IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); |
550 | 0 | return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI || |
551 | 0 | VK == RISCVMCExpr::VK_RISCV_TPREL_HI); |
552 | 0 | } else { |
553 | 0 | return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || |
554 | 0 | VK == RISCVMCExpr::VK_RISCV_HI || |
555 | 0 | VK == RISCVMCExpr::VK_RISCV_TPREL_HI); |
556 | 0 | } |
557 | 0 | } |
558 | | |
559 | 0 | bool isUImm20AUIPC() const { |
560 | 0 | RISCVMCExpr::VariantKind VK; |
561 | 0 | int64_t Imm; |
562 | 0 | bool IsValid; |
563 | 0 | if (!isImm()) |
564 | 0 | return false; |
565 | 0 | bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); |
566 | 0 | if (!IsConstantImm) { |
567 | 0 | IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); |
568 | 0 | return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI || |
569 | 0 | VK == RISCVMCExpr::VK_RISCV_GOT_HI || |
570 | 0 | VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || |
571 | 0 | VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); |
572 | 0 | } else { |
573 | 0 | return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || |
574 | 0 | VK == RISCVMCExpr::VK_RISCV_PCREL_HI || |
575 | 0 | VK == RISCVMCExpr::VK_RISCV_GOT_HI || |
576 | 0 | VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || |
577 | 0 | VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); |
578 | 0 | } |
579 | 0 | } |
580 | | |
581 | 743 | bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); } |
582 | | |
583 | | /// getStartLoc - Gets location of the first token of this operand |
584 | 386 | SMLoc getStartLoc() const override { return StartLoc; } |
585 | | /// getEndLoc - Gets location of the last token of this operand |
586 | 0 | SMLoc getEndLoc() const override { return EndLoc; } |
587 | | /// True if this operand is for an RV64 instruction |
588 | 0 | bool isRV64() const { return IsRV64; } |
589 | | |
590 | 92 | unsigned getReg() const override { |
591 | 92 | assert(Kind == Register && "Invalid type access!"); |
592 | 0 | return Reg.RegNum; |
593 | 92 | } |
594 | | |
595 | 0 | StringRef getSysReg() const { |
596 | 0 | assert(Kind == SystemRegister && "Invalid access!"); |
597 | 0 | return StringRef(SysReg.Data, SysReg.Length); |
598 | 0 | } |
599 | | |
600 | 1.61k | const MCExpr *getImm() const { |
601 | 1.61k | assert(Kind == Immediate && "Invalid type access!"); |
602 | 0 | return Imm.Val; |
603 | 1.61k | } |
604 | | |
605 | 4.42k | StringRef getToken() const { |
606 | 4.42k | assert(Kind == Token && "Invalid type access!"); |
607 | 0 | return Tok; |
608 | 4.42k | } |
609 | | |
610 | 0 | void print(raw_ostream &OS) const override { |
611 | 0 | switch (Kind) { |
612 | 0 | case Immediate: |
613 | 0 | OS << *getImm(); |
614 | 0 | break; |
615 | 0 | case Register: |
616 | 0 | OS << "<register x"; |
617 | 0 | OS << getReg() << ">"; |
618 | 0 | break; |
619 | 0 | case Token: |
620 | 0 | OS << "'" << getToken() << "'"; |
621 | 0 | break; |
622 | 0 | case SystemRegister: |
623 | 0 | OS << "<sysreg: " << getSysReg() << '>'; |
624 | 0 | break; |
625 | 0 | } |
626 | 0 | } |
627 | | |
628 | | static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S, |
629 | 26.4k | bool IsRV64) { |
630 | 26.4k | auto Op = make_unique<RISCVOperand>(Token); |
631 | 26.4k | Op->Tok = Str; |
632 | 26.4k | Op->StartLoc = S; |
633 | 26.4k | Op->EndLoc = S; |
634 | 26.4k | Op->IsRV64 = IsRV64; |
635 | 26.4k | return Op; |
636 | 26.4k | } |
637 | | |
638 | | static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S, |
639 | 1.54k | SMLoc E, bool IsRV64) { |
640 | 1.54k | auto Op = make_unique<RISCVOperand>(Register); |
641 | 1.54k | Op->Reg.RegNum = RegNo; |
642 | 1.54k | Op->StartLoc = S; |
643 | 1.54k | Op->EndLoc = E; |
644 | 1.54k | Op->IsRV64 = IsRV64; |
645 | 1.54k | return Op; |
646 | 1.54k | } |
647 | | |
648 | | static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S, |
649 | 56.7k | SMLoc E, bool IsRV64) { |
650 | 56.7k | auto Op = make_unique<RISCVOperand>(Immediate); |
651 | 56.7k | Op->Imm.Val = Val; |
652 | 56.7k | Op->StartLoc = S; |
653 | 56.7k | Op->EndLoc = E; |
654 | 56.7k | Op->IsRV64 = IsRV64; |
655 | 56.7k | return Op; |
656 | 56.7k | } |
657 | | |
658 | | static std::unique_ptr<RISCVOperand> |
659 | 24 | createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) { |
660 | 24 | auto Op = make_unique<RISCVOperand>(SystemRegister); |
661 | 24 | Op->SysReg.Data = Str.data(); |
662 | 24 | Op->SysReg.Length = Str.size(); |
663 | 24 | Op->SysReg.Encoding = Encoding; |
664 | 24 | Op->StartLoc = S; |
665 | 24 | Op->IsRV64 = IsRV64; |
666 | 24 | return Op; |
667 | 24 | } |
668 | | |
669 | 668 | void addExpr(MCInst &Inst, const MCExpr *Expr) const { |
670 | 668 | assert(Expr && "Expr shouldn't be null!"); |
671 | 0 | int64_t Imm = 0; |
672 | 668 | RISCVMCExpr::VariantKind VK; |
673 | 668 | bool IsConstant = evaluateConstantImm(Expr, Imm, VK); |
674 | | |
675 | 668 | if (IsConstant) |
676 | 583 | Inst.addOperand(MCOperand::createImm(Imm)); |
677 | 85 | else |
678 | 85 | Inst.addOperand(MCOperand::createExpr(Expr)); |
679 | 668 | } |
680 | | |
681 | | // Used by the TableGen Code |
682 | 2 | void addRegOperands(MCInst &Inst, unsigned N) const { |
683 | 2 | assert(N == 1 && "Invalid number of operands!"); |
684 | 0 | Inst.addOperand(MCOperand::createReg(getReg())); |
685 | 2 | } |
686 | | |
687 | 668 | void addImmOperands(MCInst &Inst, unsigned N) const { |
688 | 668 | assert(N == 1 && "Invalid number of operands!"); |
689 | 0 | addExpr(Inst, getImm()); |
690 | 668 | } |
691 | | |
692 | 0 | void addFenceArgOperands(MCInst &Inst, unsigned N) const { |
693 | 0 | assert(N == 1 && "Invalid number of operands!"); |
694 | | // isFenceArg has validated the operand, meaning this cast is safe |
695 | 0 | auto SE = cast<MCSymbolRefExpr>(getImm()); |
696 | |
|
697 | 0 | unsigned Imm = 0; |
698 | 0 | for (char c : SE->getSymbol().getName()) { |
699 | 0 | switch (c) { |
700 | 0 | default: |
701 | 0 | llvm_unreachable("FenceArg must contain only [iorw]"); |
702 | 0 | case 'i': Imm |= RISCVFenceField::I; break; |
703 | 0 | case 'o': Imm |= RISCVFenceField::O; break; |
704 | 0 | case 'r': Imm |= RISCVFenceField::R; break; |
705 | 0 | case 'w': Imm |= RISCVFenceField::W; break; |
706 | 0 | } |
707 | 0 | } |
708 | 0 | Inst.addOperand(MCOperand::createImm(Imm)); |
709 | 0 | } |
710 | | |
711 | 3 | void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { |
712 | 3 | assert(N == 1 && "Invalid number of operands!"); |
713 | 0 | Inst.addOperand(MCOperand::createImm(SysReg.Encoding)); |
714 | 3 | } |
715 | | |
716 | | // Returns the rounding mode represented by this RISCVOperand. Should only |
717 | | // be called after checking isFRMArg. |
718 | 0 | RISCVFPRndMode::RoundingMode getRoundingMode() const { |
719 | | // isFRMArg has validated the operand, meaning this cast is safe. |
720 | 0 | auto SE = cast<MCSymbolRefExpr>(getImm()); |
721 | 0 | RISCVFPRndMode::RoundingMode FRM = |
722 | 0 | RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName()); |
723 | 0 | assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode"); |
724 | 0 | return FRM; |
725 | 0 | } |
726 | | |
727 | 0 | void addFRMArgOperands(MCInst &Inst, unsigned N) const { |
728 | 0 | assert(N == 1 && "Invalid number of operands!"); |
729 | 0 | Inst.addOperand(MCOperand::createImm(getRoundingMode())); |
730 | 0 | } |
731 | | }; |
732 | | } // end anonymous namespace. |
733 | | |
734 | | #define GET_REGISTER_MATCHER |
735 | | #define GET_MATCHER_IMPLEMENTATION |
736 | | #include "RISCVGenAsmMatcher.inc" |
737 | | |
738 | | // Return the matching FPR64 register for the given FPR32. |
739 | | // FIXME: Ideally this function could be removed in favour of using |
740 | | // information from TableGen. |
741 | 0 | unsigned convertFPR32ToFPR64(unsigned Reg) { |
742 | 0 | switch (Reg) { |
743 | 0 | default: |
744 | 0 | llvm_unreachable("Not a recognised FPR32 register"); |
745 | 0 | case RISCV::F0_32: return RISCV::F0_64; |
746 | 0 | case RISCV::F1_32: return RISCV::F1_64; |
747 | 0 | case RISCV::F2_32: return RISCV::F2_64; |
748 | 0 | case RISCV::F3_32: return RISCV::F3_64; |
749 | 0 | case RISCV::F4_32: return RISCV::F4_64; |
750 | 0 | case RISCV::F5_32: return RISCV::F5_64; |
751 | 0 | case RISCV::F6_32: return RISCV::F6_64; |
752 | 0 | case RISCV::F7_32: return RISCV::F7_64; |
753 | 0 | case RISCV::F8_32: return RISCV::F8_64; |
754 | 0 | case RISCV::F9_32: return RISCV::F9_64; |
755 | 0 | case RISCV::F10_32: return RISCV::F10_64; |
756 | 0 | case RISCV::F11_32: return RISCV::F11_64; |
757 | 0 | case RISCV::F12_32: return RISCV::F12_64; |
758 | 0 | case RISCV::F13_32: return RISCV::F13_64; |
759 | 0 | case RISCV::F14_32: return RISCV::F14_64; |
760 | 0 | case RISCV::F15_32: return RISCV::F15_64; |
761 | 0 | case RISCV::F16_32: return RISCV::F16_64; |
762 | 0 | case RISCV::F17_32: return RISCV::F17_64; |
763 | 0 | case RISCV::F18_32: return RISCV::F18_64; |
764 | 0 | case RISCV::F19_32: return RISCV::F19_64; |
765 | 0 | case RISCV::F20_32: return RISCV::F20_64; |
766 | 0 | case RISCV::F21_32: return RISCV::F21_64; |
767 | 0 | case RISCV::F22_32: return RISCV::F22_64; |
768 | 0 | case RISCV::F23_32: return RISCV::F23_64; |
769 | 0 | case RISCV::F24_32: return RISCV::F24_64; |
770 | 0 | case RISCV::F25_32: return RISCV::F25_64; |
771 | 0 | case RISCV::F26_32: return RISCV::F26_64; |
772 | 0 | case RISCV::F27_32: return RISCV::F27_64; |
773 | 0 | case RISCV::F28_32: return RISCV::F28_64; |
774 | 0 | case RISCV::F29_32: return RISCV::F29_64; |
775 | 0 | case RISCV::F30_32: return RISCV::F30_64; |
776 | 0 | case RISCV::F31_32: return RISCV::F31_64; |
777 | 0 | } |
778 | 0 | } |
779 | | |
780 | | unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, |
781 | 363 | unsigned Kind) { |
782 | 363 | RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp); |
783 | 363 | if (!Op.isReg()) |
784 | 359 | return Match_InvalidOperand; |
785 | | |
786 | 4 | unsigned Reg = Op.getReg(); |
787 | 4 | bool IsRegFPR32 = |
788 | 4 | RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg); |
789 | 4 | bool IsRegFPR32C = |
790 | 4 | RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg); |
791 | | |
792 | | // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the |
793 | | // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary. |
794 | 4 | if ((IsRegFPR32 && Kind == MCK_FPR64) || |
795 | 4 | (IsRegFPR32C && Kind == MCK_FPR64C)) { |
796 | 0 | Op.Reg.RegNum = convertFPR32ToFPR64(Reg); |
797 | 0 | return Match_Success; |
798 | 0 | } |
799 | 4 | return Match_InvalidOperand; |
800 | 4 | } |
801 | | |
802 | | bool RISCVAsmParser::generateImmOutOfRangeError( |
803 | | OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, |
804 | 133 | Twine Msg = "immediate must be an integer in the range") { |
805 | 133 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
806 | 133 | return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); |
807 | | //FIXME: gracefully return error to keystone |
808 | 133 | } |
809 | | |
810 | | bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, |
811 | | OperandVector &Operands, |
812 | | MCStreamer &Out, |
813 | | uint64_t &ErrorInfo, |
814 | 4.60k | bool MatchingInlineAsm, unsigned int &ErrorCode, uint64_t &Address) { |
815 | 4.60k | MCInst Inst(Address); |
816 | 4.60k | unsigned Result = |
817 | 4.60k | MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); |
818 | 4.60k | switch (Result) { |
819 | 149 | default: |
820 | 149 | break; |
821 | 1.09k | case Match_Success: |
822 | 1.09k | return processInstruction(Inst, IDLoc, Operands, Out); |
823 | 0 | case Match_MissingFeature: |
824 | | // Return error to Keystone |
825 | 0 | ErrorCode = KS_ERR_ASM_RISCV_MISSINGFEATURE; |
826 | 0 | return true; |
827 | 3.12k | case Match_MnemonicFail: |
828 | | // Return error to Keystone |
829 | 3.12k | ErrorCode = KS_ERR_ASM_RISCV_MNEMONICFAIL; |
830 | 3.12k | return true; |
831 | 237 | case Match_InvalidOperand: { |
832 | 237 | SMLoc ErrorLoc = IDLoc; |
833 | 237 | if (ErrorInfo != ~0U) { |
834 | 237 | if (ErrorInfo >= Operands.size()) |
835 | | // Return error to Keystone |
836 | 0 | ErrorCode = KS_ERR_ASM_RISCV_INVALIDOPERAND; |
837 | | |
838 | 237 | ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
839 | 237 | if (ErrorLoc == SMLoc()) |
840 | 0 | ErrorLoc = IDLoc; |
841 | 237 | } |
842 | | // Return error to Keystone |
843 | 237 | ErrorCode = KS_ERR_ASM_RISCV_INVALIDOPERAND; |
844 | 237 | return true; |
845 | 0 | } |
846 | 4.60k | } |
847 | | |
848 | | // Handle the case when the error message is of specific type |
849 | | // other than the generic Match_InvalidOperand, and the |
850 | | // corresponding operand is missing. |
851 | 149 | if (Result > FIRST_TARGET_MATCH_RESULT_TY) { |
852 | 149 | SMLoc ErrorLoc = IDLoc; |
853 | 149 | if (ErrorInfo != ~0U && ErrorInfo >= Operands.size()) |
854 | 0 | return Error(ErrorLoc, "too few operands for instruction"); |
855 | | // throw a separate error, since there is no errorcode in Keystone |
856 | | // FIXME: add situation specific error to indicate this and avoid throwing errors in favor of gracefully returning keystone error code |
857 | 149 | } |
858 | | |
859 | 149 | switch(Result) { |
860 | 0 | default: |
861 | 0 | break; |
862 | 0 | case Match_InvalidImmXLenLI: |
863 | 0 | if (isRV64()) { |
864 | 0 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
865 | 0 | return Error(ErrorLoc, "operand must be a constant 64-bit integer"); |
866 | | //FIXME: gracefully return error to keystone |
867 | 0 | } |
868 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, |
869 | 0 | std::numeric_limits<int32_t>::min(), |
870 | 0 | std::numeric_limits<uint32_t>::max()); |
871 | 0 | case Match_InvalidUImmLog2XLen: |
872 | 0 | if (isRV64()) |
873 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); |
874 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); |
875 | 0 | case Match_InvalidUImmLog2XLenNonZero: |
876 | 0 | if (isRV64()) |
877 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); |
878 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); |
879 | 1 | case Match_InvalidUImm5: |
880 | 1 | return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); |
881 | 0 | case Match_InvalidSImm6: |
882 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), |
883 | 0 | (1 << 5) - 1); |
884 | 0 | case Match_InvalidSImm6NonZero: |
885 | 0 | return generateImmOutOfRangeError( |
886 | 0 | Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1, |
887 | 0 | "immediate must be non-zero in the range"); |
888 | 0 | case Match_InvalidCLUIImm: |
889 | 0 | return generateImmOutOfRangeError( |
890 | 0 | Operands, ErrorInfo, 1, (1 << 5) - 1, |
891 | 0 | "immediate must be in [0xfffe0, 0xfffff] or"); |
892 | 0 | case Match_InvalidUImm7Lsb00: |
893 | 0 | return generateImmOutOfRangeError( |
894 | 0 | Operands, ErrorInfo, 0, (1 << 7) - 4, |
895 | 0 | "immediate must be a multiple of 4 bytes in the range"); |
896 | 0 | case Match_InvalidUImm8Lsb00: |
897 | 0 | return generateImmOutOfRangeError( |
898 | 0 | Operands, ErrorInfo, 0, (1 << 8) - 4, |
899 | 0 | "immediate must be a multiple of 4 bytes in the range"); |
900 | 0 | case Match_InvalidUImm8Lsb000: |
901 | 0 | return generateImmOutOfRangeError( |
902 | 0 | Operands, ErrorInfo, 0, (1 << 8) - 8, |
903 | 0 | "immediate must be a multiple of 8 bytes in the range"); |
904 | 0 | case Match_InvalidSImm9Lsb0: |
905 | 0 | return generateImmOutOfRangeError( |
906 | 0 | Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2, |
907 | 0 | "immediate must be a multiple of 2 bytes in the range"); |
908 | 0 | case Match_InvalidUImm9Lsb000: |
909 | 0 | return generateImmOutOfRangeError( |
910 | 0 | Operands, ErrorInfo, 0, (1 << 9) - 8, |
911 | 0 | "immediate must be a multiple of 8 bytes in the range"); |
912 | 0 | case Match_InvalidUImm10Lsb00NonZero: |
913 | 0 | return generateImmOutOfRangeError( |
914 | 0 | Operands, ErrorInfo, 4, (1 << 10) - 4, |
915 | 0 | "immediate must be a multiple of 4 bytes in the range"); |
916 | 0 | case Match_InvalidSImm10Lsb0000NonZero: |
917 | 0 | return generateImmOutOfRangeError( |
918 | 0 | Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16, |
919 | 0 | "immediate must be a multiple of 16 bytes and non-zero in the range"); |
920 | 17 | case Match_InvalidSImm12: |
921 | 17 | return generateImmOutOfRangeError( |
922 | 17 | Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1, |
923 | 17 | "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an " |
924 | 17 | "integer in the range"); |
925 | 0 | case Match_InvalidSImm12Lsb0: |
926 | 0 | return generateImmOutOfRangeError( |
927 | 0 | Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, |
928 | 0 | "immediate must be a multiple of 2 bytes in the range"); |
929 | 0 | case Match_InvalidSImm13Lsb0: |
930 | 0 | return generateImmOutOfRangeError( |
931 | 0 | Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, |
932 | 0 | "immediate must be a multiple of 2 bytes in the range"); |
933 | 0 | case Match_InvalidUImm20LUI: |
934 | 0 | return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1, |
935 | 0 | "operand must be a symbol with " |
936 | 0 | "%hi/%tprel_hi modifier or an integer in " |
937 | 0 | "the range"); |
938 | 0 | case Match_InvalidUImm20AUIPC: |
939 | 0 | return generateImmOutOfRangeError( |
940 | 0 | Operands, ErrorInfo, 0, (1 << 20) - 1, |
941 | 0 | "operand must be a symbol with a " |
942 | 0 | "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or " |
943 | 0 | "an integer in the range"); |
944 | 113 | case Match_InvalidSImm21Lsb0JAL: |
945 | 113 | return generateImmOutOfRangeError( |
946 | 113 | Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, |
947 | 113 | "immediate must be a multiple of 2 bytes in the range"); |
948 | 2 | case Match_InvalidCSRSystemRegister: { |
949 | 2 | return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1, |
950 | 2 | "operand must be a valid system register " |
951 | 2 | "name or an integer in the range"); |
952 | 0 | } |
953 | 1 | case Match_InvalidFenceArg: { |
954 | 1 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
955 | 1 | return Error( |
956 | 1 | ErrorLoc, |
957 | 1 | "operand must be formed of letters selected in-order from 'iorw'"); |
958 | 0 | } |
959 | 0 | case Match_InvalidFRMArg: { |
960 | 0 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
961 | 0 | return Error( |
962 | 0 | ErrorLoc, |
963 | 0 | "operand must be a valid floating point rounding mode mnemonic"); |
964 | 0 | } |
965 | 0 | case Match_InvalidBareSymbol: { |
966 | 0 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
967 | 0 | return Error(ErrorLoc, "operand must be a bare symbol name"); |
968 | 0 | } |
969 | 15 | case Match_InvalidCallSymbol: { |
970 | 15 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
971 | 15 | return Error(ErrorLoc, "operand must be a bare symbol name"); |
972 | 0 | } |
973 | 0 | case Match_InvalidTPRelAddSymbol: { |
974 | 0 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); |
975 | 0 | return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier"); |
976 | 0 | } |
977 | 149 | } |
978 | | |
979 | 149 | llvm_unreachable("Unknown match type detected!"); |
980 | 149 | } |
981 | | |
982 | | // Attempts to match Name as a register (either using the default name or |
983 | | // alternative ABI names), setting RegNo to the matching register. Upon |
984 | | // failure, returns true and sets RegNo to 0. If IsRV32E then registers |
985 | | // x16-x31 will be rejected. |
986 | | static bool matchRegisterNameHelper(bool IsRV32E, unsigned &RegNo, |
987 | 51.3k | StringRef Name) { |
988 | 51.3k | RegNo = MatchRegisterName(Name); |
989 | 51.3k | if (RegNo == 0) |
990 | 51.2k | RegNo = MatchRegisterAltName(Name); |
991 | 51.3k | if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31) |
992 | 0 | RegNo = 0; |
993 | 51.3k | return RegNo == 0; |
994 | 51.3k | } |
995 | | |
996 | | bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, |
997 | 0 | SMLoc &EndLoc, unsigned int &ErrorCode) { |
998 | 0 | const AsmToken &Tok = getParser().getTok(); |
999 | 0 | StartLoc = Tok.getLoc(); |
1000 | 0 | EndLoc = Tok.getEndLoc(); |
1001 | 0 | RegNo = 0; |
1002 | 0 | StringRef Name = getLexer().getTok().getIdentifier(); |
1003 | |
|
1004 | 0 | if (matchRegisterNameHelper(isRV32E(), RegNo, Name)) |
1005 | 0 | return Error(StartLoc, "invalid register name"); |
1006 | | |
1007 | 0 | getParser().Lex(); // Eat identifier token. |
1008 | 0 | return false; |
1009 | 0 | } |
1010 | | |
1011 | | RISCVAsmParser::OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands, |
1012 | 75.0k | bool AllowParens, unsigned int &KsError) { |
1013 | 75.0k | SMLoc FirstS = getLoc(); |
1014 | 75.0k | bool HadParens = false; |
1015 | 75.0k | AsmToken LParen; |
1016 | | |
1017 | | // If this is an LParen and a parenthesised register name is allowed, parse it |
1018 | | // atomically. |
1019 | 75.0k | if (AllowParens && getLexer().is(AsmToken::LParen)) { |
1020 | 2.76k | AsmToken Buf[2]; |
1021 | 2.76k | size_t ReadCount = getLexer().peekTokens(Buf); |
1022 | 2.76k | if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { |
1023 | 142 | HadParens = true; |
1024 | 142 | LParen = getParser().getTok(); |
1025 | 142 | getParser().Lex(); // Eat '(' |
1026 | 142 | } |
1027 | 2.76k | } |
1028 | | |
1029 | 75.0k | switch (getLexer().getKind()) { |
1030 | 23.6k | default: |
1031 | 23.6k | if (HadParens) |
1032 | 31 | getLexer().UnLex(LParen); |
1033 | 23.6k | return MatchOperand_NoMatch; |
1034 | 51.3k | case AsmToken::Identifier: |
1035 | 51.3k | StringRef Name = getLexer().getTok().getIdentifier(); |
1036 | 51.3k | unsigned RegNo; |
1037 | 51.3k | matchRegisterNameHelper(isRV32E(), RegNo, Name); |
1038 | | |
1039 | 51.3k | if (RegNo == 0) { |
1040 | 49.8k | if (HadParens) |
1041 | 65 | getLexer().UnLex(LParen); |
1042 | 49.8k | return MatchOperand_NoMatch; |
1043 | 49.8k | } |
1044 | 1.54k | if (HadParens) |
1045 | 46 | Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64())); |
1046 | 1.54k | SMLoc S = getLoc(); |
1047 | 1.54k | SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); |
1048 | 1.54k | getLexer().Lex(); |
1049 | 1.54k | Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64())); |
1050 | 75.0k | } |
1051 | | |
1052 | 1.54k | if (HadParens) { |
1053 | 46 | getParser().Lex(); // Eat ')' |
1054 | 46 | Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64())); |
1055 | 46 | } |
1056 | | |
1057 | 1.54k | return MatchOperand_Success; |
1058 | 75.0k | } |
1059 | | |
1060 | | RISCVAsmParser::OperandMatchResultTy |
1061 | 253 | RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) { |
1062 | 253 | SMLoc S = getLoc(); |
1063 | 253 | const MCExpr *Res; |
1064 | | |
1065 | 253 | switch (getLexer().getKind()) { |
1066 | 22 | default: |
1067 | 22 | return MatchOperand_NoMatch; |
1068 | 3 | case AsmToken::LParen: |
1069 | 36 | case AsmToken::Minus: |
1070 | 40 | case AsmToken::Plus: |
1071 | 44 | case AsmToken::Exclaim: |
1072 | 48 | case AsmToken::Tilde: |
1073 | 115 | case AsmToken::Integer: |
1074 | 117 | case AsmToken::String: { |
1075 | 117 | if (getParser().parseExpression(Res)) |
1076 | 24 | return MatchOperand_ParseFail; |
1077 | | |
1078 | 93 | auto *CE = dyn_cast<MCConstantExpr>(Res); |
1079 | 93 | if (CE) { |
1080 | 87 | int64_t Imm = CE->getValue(); |
1081 | 87 | if (isUInt<12>(Imm)) { |
1082 | 22 | auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm); |
1083 | | // Accept an immediate representing a named or un-named Sys Reg |
1084 | | // if the range is valid, regardless of the required features. |
1085 | 22 | Operands.push_back(RISCVOperand::createSysReg( |
1086 | 22 | SysReg ? SysReg->Name : "", S, Imm, isRV64())); |
1087 | 22 | return MatchOperand_Success; |
1088 | 22 | } |
1089 | 87 | } |
1090 | | |
1091 | 71 | Twine Msg = "immediate must be an integer in the range"; |
1092 | 71 | Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); |
1093 | 71 | return MatchOperand_ParseFail; |
1094 | 93 | } |
1095 | 112 | case AsmToken::Identifier: { |
1096 | 112 | StringRef Identifier; |
1097 | 112 | if (getParser().parseIdentifier(Identifier)) |
1098 | 0 | return MatchOperand_ParseFail; |
1099 | | |
1100 | 112 | auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier); |
1101 | | // Accept a named Sys Reg if the required features are present. |
1102 | 112 | if (SysReg) { |
1103 | 2 | if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) { |
1104 | 0 | Error(S, "system register use requires an option to be enabled"); |
1105 | 0 | return MatchOperand_ParseFail; |
1106 | 0 | } |
1107 | 2 | Operands.push_back(RISCVOperand::createSysReg( |
1108 | 2 | Identifier, S, SysReg->Encoding, isRV64())); |
1109 | 2 | return MatchOperand_Success; |
1110 | 2 | } |
1111 | | |
1112 | 110 | Twine Msg = "operand must be a valid system register name " |
1113 | 110 | "or an integer in the range"; |
1114 | 110 | Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); |
1115 | 110 | return MatchOperand_ParseFail; |
1116 | 112 | } |
1117 | 2 | case AsmToken::Percent: { |
1118 | | // Discard operand with modifier. |
1119 | 2 | Twine Msg = "immediate must be an integer in the range"; |
1120 | 2 | Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); |
1121 | 2 | return MatchOperand_ParseFail; |
1122 | 112 | } |
1123 | 253 | } |
1124 | | |
1125 | 0 | return MatchOperand_NoMatch; |
1126 | 253 | } |
1127 | | |
1128 | 74.4k | RISCVAsmParser::OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) { |
1129 | 74.4k | SMLoc S = getLoc(); |
1130 | 74.4k | SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); |
1131 | 74.4k | const MCExpr *Res; |
1132 | | |
1133 | 74.4k | switch (getLexer().getKind()) { |
1134 | 1.08k | default: |
1135 | 1.08k | return MatchOperand_NoMatch; |
1136 | 2.72k | case AsmToken::LParen: |
1137 | 4.39k | case AsmToken::Dot: |
1138 | 12.9k | case AsmToken::Minus: |
1139 | 14.9k | case AsmToken::Plus: |
1140 | 16.2k | case AsmToken::Exclaim: |
1141 | 18.4k | case AsmToken::Tilde: |
1142 | 22.2k | case AsmToken::Integer: |
1143 | 23.0k | case AsmToken::String: |
1144 | 72.9k | case AsmToken::Identifier: |
1145 | 72.9k | if (getParser().parseExpression(Res)) |
1146 | 16.8k | return MatchOperand_ParseFail; |
1147 | 56.1k | break; |
1148 | 56.1k | case AsmToken::Percent: |
1149 | 427 | return parseOperandWithModifier(Operands); |
1150 | 74.4k | } |
1151 | | |
1152 | 56.1k | Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); |
1153 | 56.1k | return MatchOperand_Success; |
1154 | 74.4k | } |
1155 | | |
1156 | | RISCVAsmParser::OperandMatchResultTy |
1157 | 432 | RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) { |
1158 | 432 | SMLoc S = getLoc(); |
1159 | 432 | SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); |
1160 | | |
1161 | 432 | if (getLexer().getKind() != AsmToken::Percent) { |
1162 | 5 | Error(getLoc(), "expected '%' for operand modifier"); |
1163 | 5 | return MatchOperand_ParseFail; |
1164 | 5 | } |
1165 | | |
1166 | 427 | getParser().Lex(); // Eat '%' |
1167 | | |
1168 | 427 | if (getLexer().getKind() != AsmToken::Identifier) { |
1169 | 57 | Error(getLoc(), "expected valid identifier for operand modifier"); |
1170 | 57 | return MatchOperand_ParseFail; |
1171 | 57 | } |
1172 | 370 | StringRef Identifier = getParser().getTok().getIdentifier(); |
1173 | 370 | RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier); |
1174 | 370 | if (VK == RISCVMCExpr::VK_RISCV_Invalid) { |
1175 | 205 | Error(getLoc(), "unrecognized operand modifier"); |
1176 | 205 | return MatchOperand_ParseFail; |
1177 | 205 | } |
1178 | | |
1179 | 165 | getParser().Lex(); // Eat the identifier |
1180 | 165 | if (getLexer().getKind() != AsmToken::LParen) { |
1181 | 10 | Error(getLoc(), "expected '('"); |
1182 | 10 | return MatchOperand_ParseFail; |
1183 | 10 | } |
1184 | 155 | getParser().Lex(); // Eat '(' |
1185 | | |
1186 | 155 | const MCExpr *SubExpr; |
1187 | 155 | if (getParser().parseParenExpression(SubExpr, E)) { |
1188 | 153 | return MatchOperand_ParseFail; |
1189 | 153 | } |
1190 | | |
1191 | 2 | const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext()); |
1192 | 2 | Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64())); |
1193 | 2 | return MatchOperand_Success; |
1194 | 155 | } |
1195 | | |
1196 | 614 | RISCVAsmParser::OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { |
1197 | 614 | SMLoc S = getLoc(); |
1198 | 614 | SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); |
1199 | 614 | const MCExpr *Res; |
1200 | | |
1201 | 614 | if (getLexer().getKind() != AsmToken::Identifier) |
1202 | 66 | return MatchOperand_NoMatch; |
1203 | | |
1204 | 548 | StringRef Identifier; |
1205 | 548 | AsmToken Tok = getLexer().getTok(); |
1206 | | |
1207 | 548 | if (getParser().parseIdentifier(Identifier)) |
1208 | 0 | return MatchOperand_ParseFail; |
1209 | | |
1210 | 548 | if (Identifier.consume_back("@plt")) { |
1211 | 3 | Error(getLoc(), "'@plt' operand not valid for instruction"); |
1212 | 3 | return MatchOperand_ParseFail; |
1213 | 3 | } |
1214 | | |
1215 | 545 | MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); |
1216 | | |
1217 | 545 | if (Sym->isVariable()) { |
1218 | 0 | const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); |
1219 | 0 | if (!isa<MCSymbolRefExpr>(V)) { |
1220 | 0 | getLexer().UnLex(Tok); // Put back if it's not a bare symbol. |
1221 | 0 | return MatchOperand_NoMatch; |
1222 | 0 | } |
1223 | 0 | Res = V; |
1224 | 0 | } else |
1225 | 545 | Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); |
1226 | | |
1227 | 545 | MCBinaryExpr::Opcode Opcode; |
1228 | 545 | switch (getLexer().getKind()) { |
1229 | 374 | default: |
1230 | 374 | Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); |
1231 | 374 | return MatchOperand_Success; |
1232 | 22 | case AsmToken::Plus: |
1233 | 22 | Opcode = MCBinaryExpr::Add; |
1234 | 22 | break; |
1235 | 149 | case AsmToken::Minus: |
1236 | 149 | Opcode = MCBinaryExpr::Sub; |
1237 | 149 | break; |
1238 | 545 | } |
1239 | | |
1240 | 171 | const MCExpr *Expr; |
1241 | 171 | if (getParser().parseExpression(Expr)) |
1242 | 8 | return MatchOperand_ParseFail; |
1243 | 163 | Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); |
1244 | 163 | Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); |
1245 | 163 | return MatchOperand_Success; |
1246 | 171 | } |
1247 | | |
1248 | 191 | RISCVAsmParser::OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) { |
1249 | 191 | SMLoc S = getLoc(); |
1250 | 191 | SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); |
1251 | 191 | const MCExpr *Res; |
1252 | | |
1253 | 191 | if (getLexer().getKind() != AsmToken::Identifier) |
1254 | 46 | return MatchOperand_NoMatch; |
1255 | | |
1256 | | // Avoid parsing the register in `call rd, foo` as a call symbol. |
1257 | 145 | if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement) |
1258 | 107 | return MatchOperand_NoMatch; |
1259 | | |
1260 | 38 | StringRef Identifier; |
1261 | 38 | if (getParser().parseIdentifier(Identifier)) |
1262 | 0 | return MatchOperand_ParseFail; |
1263 | | |
1264 | 38 | RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL; |
1265 | 38 | if (Identifier.consume_back("@plt")) |
1266 | 0 | Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; |
1267 | | |
1268 | 38 | MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); |
1269 | 38 | Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); |
1270 | 38 | Res = RISCVMCExpr::create(Res, Kind, getContext()); |
1271 | 38 | Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); |
1272 | 38 | return MatchOperand_Success; |
1273 | 38 | } |
1274 | | |
1275 | 1.22k | RISCVAsmParser::OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) { |
1276 | | // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo` |
1277 | | // both being acceptable forms. When parsing `jal ra, foo` this function |
1278 | | // will be called for the `ra` register operand in an attempt to match the |
1279 | | // single-operand alias. parseJALOffset must fail for this case. It would |
1280 | | // seem logical to try parse the operand using parseImmediate and return |
1281 | | // NoMatch if the next token is a comma (meaning we must be parsing a jal in |
1282 | | // the second form rather than the first). We can't do this as there's no |
1283 | | // way of rewinding the lexer state. Instead, return NoMatch if this operand |
1284 | | // is an identifier and is followed by a comma. |
1285 | 1.22k | if (getLexer().is(AsmToken::Identifier) && |
1286 | 1.22k | getLexer().peekTok().is(AsmToken::Comma)) |
1287 | 140 | return MatchOperand_NoMatch; |
1288 | | |
1289 | 1.08k | return parseImmediate(Operands); |
1290 | 1.22k | } |
1291 | | |
1292 | | RISCVAsmParser::OperandMatchResultTy |
1293 | 228 | RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) { |
1294 | 228 | if (getLexer().isNot(AsmToken::LParen)) { |
1295 | 0 | Error(getLoc(), "expected '('"); |
1296 | 0 | return MatchOperand_ParseFail; |
1297 | 0 | } |
1298 | | |
1299 | 228 | getParser().Lex(); // Eat '(' |
1300 | 228 | Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64())); |
1301 | | |
1302 | 228 | if (parseRegister(Operands) != MatchOperand_Success) { |
1303 | 81 | Error(getLoc(), "expected register"); |
1304 | 81 | return MatchOperand_ParseFail; |
1305 | 81 | } |
1306 | | |
1307 | 147 | if (getLexer().isNot(AsmToken::RParen)) { |
1308 | 17 | Error(getLoc(), "expected ')'"); |
1309 | 17 | return MatchOperand_ParseFail; |
1310 | 17 | } |
1311 | | |
1312 | 130 | getParser().Lex(); // Eat ')' |
1313 | 130 | Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64())); |
1314 | | |
1315 | 130 | return MatchOperand_Success; |
1316 | 147 | } |
1317 | | |
1318 | | /// Looks at a token type and creates the relevant operand from this |
1319 | | /// information, adding to Operands. If operand was parsed, returns false, else |
1320 | | /// true. |
1321 | 76.7k | bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { |
1322 | | // Check if the current operand has a custom associated parser, if so, try to |
1323 | | // custom parse the operand, or fallback to the general approach. |
1324 | 76.7k | OperandMatchResultTy Result = |
1325 | 76.7k | MatchOperandParserImpl(Operands, Mnemonic); |
1326 | 76.7k | if (Result == MatchOperand_Success) |
1327 | 1.59k | return false; |
1328 | 75.1k | if (Result == MatchOperand_ParseFail) |
1329 | 302 | return true; |
1330 | | |
1331 | | // Attempt to parse token as a register. |
1332 | 74.8k | if (parseRegister(Operands, true) == MatchOperand_Success) |
1333 | 1.39k | return false; |
1334 | | |
1335 | | // Attempt to parse token as an immediate |
1336 | 73.4k | if (parseImmediate(Operands) == MatchOperand_Success) { |
1337 | | // Parse memory base register if present |
1338 | 55.1k | if (getLexer().is(AsmToken::LParen)) |
1339 | 228 | return parseMemOpBaseReg(Operands) != MatchOperand_Success; |
1340 | 54.9k | return false; |
1341 | 55.1k | } |
1342 | | |
1343 | | // Finally we have exhausted all options and must declare defeat. |
1344 | 18.2k | Error(getLoc(), "unknown operand"); |
1345 | 18.2k | return true; |
1346 | 73.4k | } |
1347 | | |
1348 | | bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, |
1349 | | StringRef Name, SMLoc NameLoc, |
1350 | 25.9k | OperandVector &Operands, unsigned int &ErrorCode) { |
1351 | | |
1352 | 25.9k | DEBUG(dbgs() << "ParseInstruction\n"); |
1353 | | // Ensure that if the instruction occurs when relaxation is enabled, |
1354 | | // relocations are forced for the file. Ideally this would be done when there |
1355 | | // is enough information to reliably determine if the instruction itself may |
1356 | | // cause relaxations. Unfortunately instruction processing stage occurs in the |
1357 | | // same pass as relocation emission, so it's too late to set a 'sticky bit' |
1358 | | // for the entire file. |
1359 | 25.9k | if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) { |
1360 | 25.9k | MCAssembler &Assembler = static_cast<MCELFStreamer &>(getStreamer()).getAssembler(); |
1361 | 25.9k | auto *AssemblerPtr = &Assembler; |
1362 | 25.9k | if (AssemblerPtr != nullptr) { |
1363 | 25.9k | RISCVAsmBackend &MAB = |
1364 | 25.9k | static_cast<RISCVAsmBackend &>(AssemblerPtr->getBackend()); |
1365 | 25.9k | MAB.setForceRelocs(); |
1366 | 25.9k | } |
1367 | 25.9k | } |
1368 | | |
1369 | | // First operand is token for instruction |
1370 | 25.9k | Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64())); |
1371 | | |
1372 | | // If there are no more operands, then finish |
1373 | 25.9k | if (getLexer().is(AsmToken::EndOfStatement)) |
1374 | 1.72k | return false; |
1375 | | |
1376 | | // Parse first operand |
1377 | 24.2k | if (parseOperand(Operands, Name)) |
1378 | 16.6k | return true; |
1379 | | |
1380 | | // Parse until end of statement, consuming commas between operands |
1381 | 7.60k | unsigned OperandIdx = 1; |
1382 | 58.0k | while (getLexer().is(AsmToken::Comma)) { |
1383 | | // Consume comma token |
1384 | 52.4k | getLexer().Lex(); |
1385 | | |
1386 | | // Parse next operand |
1387 | 52.4k | if (parseOperand(Operands, Name)) |
1388 | 2.00k | return true; |
1389 | | |
1390 | 50.4k | ++OperandIdx; |
1391 | 50.4k | } |
1392 | | |
1393 | 5.59k | if (getLexer().isNot(AsmToken::EndOfStatement)) { |
1394 | 2.72k | SMLoc Loc = getLexer().getLoc(); |
1395 | 2.72k | getParser().eatToEndOfStatement(); |
1396 | 2.72k | return Error(Loc, "unexpected token"); |
1397 | 2.72k | } |
1398 | | |
1399 | 2.87k | getParser().Lex(); // Consume the EndOfStatement. |
1400 | 2.87k | return false; |
1401 | 5.59k | } |
1402 | | |
1403 | | bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr, |
1404 | | RISCVMCExpr::VariantKind &Kind, |
1405 | 128 | int64_t &Addend) { |
1406 | 128 | Kind = RISCVMCExpr::VK_RISCV_None; |
1407 | 128 | Addend = 0; |
1408 | | |
1409 | 128 | if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) { |
1410 | 35 | Kind = RE->getKind(); |
1411 | 35 | Expr = RE->getSubExpr(); |
1412 | 35 | } |
1413 | | |
1414 | | // It's a simple symbol reference or constant with no addend. |
1415 | 128 | if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr)) |
1416 | 90 | return true; |
1417 | | |
1418 | 38 | const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr); |
1419 | 38 | if (!BE) |
1420 | 9 | return false; |
1421 | | |
1422 | 29 | if (!isa<MCSymbolRefExpr>(BE->getLHS())) |
1423 | 13 | return false; |
1424 | | |
1425 | 16 | if (BE->getOpcode() != MCBinaryExpr::Add && |
1426 | 16 | BE->getOpcode() != MCBinaryExpr::Sub) |
1427 | 8 | return false; |
1428 | | |
1429 | | // We are able to support the subtraction of two symbol references |
1430 | 8 | if (BE->getOpcode() == MCBinaryExpr::Sub && |
1431 | 8 | isa<MCSymbolRefExpr>(BE->getRHS())) |
1432 | 2 | return true; |
1433 | | |
1434 | | // See if the addend is a constant, otherwise there's more going |
1435 | | // on here than we can deal with. |
1436 | 6 | auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS()); |
1437 | 6 | if (!AddendExpr) |
1438 | 2 | return false; |
1439 | | |
1440 | 4 | Addend = AddendExpr->getValue(); |
1441 | 4 | if (BE->getOpcode() == MCBinaryExpr::Sub) |
1442 | 2 | Addend = -Addend; |
1443 | | |
1444 | | // It's some symbol reference + a constant addend |
1445 | 4 | return Kind != RISCVMCExpr::VK_RISCV_Invalid; |
1446 | 6 | } |
1447 | | |
1448 | 422k | bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { |
1449 | | // This returns false if this function recognizes the directive |
1450 | | // regardless of whether it is successfully handles or reports an |
1451 | | // error. Otherwise it returns true to give the generic parser a |
1452 | | // chance at recognizing it. |
1453 | 422k | StringRef IDVal = DirectiveID.getString(); |
1454 | | |
1455 | 422k | if (IDVal == ".option") |
1456 | 3 | return parseDirectiveOption(); |
1457 | | |
1458 | 422k | return true; |
1459 | 422k | } |
1460 | | |
1461 | 3 | bool RISCVAsmParser::parseDirectiveOption() { |
1462 | 3 | MCAsmParser &Parser = getParser(); |
1463 | | // Get the option token. |
1464 | 3 | AsmToken Tok = Parser.getTok(); |
1465 | | // At the moment only identifiers are supported. |
1466 | 3 | if (Tok.isNot(AsmToken::Identifier)) |
1467 | 1 | return Error(Parser.getTok().getLoc(), |
1468 | 1 | "unexpected token, expected identifier"); |
1469 | | |
1470 | 2 | StringRef Option = Tok.getIdentifier(); |
1471 | | |
1472 | 2 | if (Option == "push") { |
1473 | 0 | getTargetStreamer().emitDirectiveOptionPush(); |
1474 | |
|
1475 | 0 | Parser.Lex(); |
1476 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1477 | 0 | return Error(Parser.getTok().getLoc(), |
1478 | 0 | "unexpected token, expected end of statement"); |
1479 | | |
1480 | 0 | pushFeatureBits(); |
1481 | 0 | return false; |
1482 | 0 | } |
1483 | | |
1484 | 2 | if (Option == "pop") { |
1485 | 0 | SMLoc StartLoc = Parser.getTok().getLoc(); |
1486 | 0 | getTargetStreamer().emitDirectiveOptionPop(); |
1487 | |
|
1488 | 0 | Parser.Lex(); |
1489 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1490 | 0 | return Error(Parser.getTok().getLoc(), |
1491 | 0 | "unexpected token, expected end of statement"); |
1492 | | |
1493 | 0 | if (popFeatureBits()) |
1494 | 0 | return Error(StartLoc, ".option pop with no .option push"); |
1495 | | |
1496 | 0 | return false; |
1497 | 0 | } |
1498 | | |
1499 | 2 | if (Option == "rvc") { |
1500 | 0 | getTargetStreamer().emitDirectiveOptionRVC(); |
1501 | |
|
1502 | 0 | Parser.Lex(); |
1503 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1504 | 0 | return Error(Parser.getTok().getLoc(), |
1505 | 0 | "unexpected token, expected end of statement"); |
1506 | | |
1507 | 0 | setFeatureBits(RISCV::FeatureStdExtC, "c"); |
1508 | 0 | return false; |
1509 | 0 | } |
1510 | | |
1511 | 2 | if (Option == "norvc") { |
1512 | 0 | getTargetStreamer().emitDirectiveOptionNoRVC(); |
1513 | |
|
1514 | 0 | Parser.Lex(); |
1515 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1516 | 0 | return Error(Parser.getTok().getLoc(), |
1517 | 0 | "unexpected token, expected end of statement"); |
1518 | | |
1519 | 0 | clearFeatureBits(RISCV::FeatureStdExtC, "c"); |
1520 | 0 | return false; |
1521 | 0 | } |
1522 | | |
1523 | 2 | if (Option == "relax") { |
1524 | 0 | getTargetStreamer().emitDirectiveOptionRelax(); |
1525 | |
|
1526 | 0 | Parser.Lex(); |
1527 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1528 | 0 | return Error(Parser.getTok().getLoc(), |
1529 | 0 | "unexpected token, expected end of statement"); |
1530 | | |
1531 | 0 | setFeatureBits(RISCV::FeatureRelax, "relax"); |
1532 | 0 | return false; |
1533 | 0 | } |
1534 | | |
1535 | 2 | if (Option == "norelax") { |
1536 | 0 | getTargetStreamer().emitDirectiveOptionNoRelax(); |
1537 | |
|
1538 | 0 | Parser.Lex(); |
1539 | 0 | if (Parser.getTok().isNot(AsmToken::EndOfStatement)) |
1540 | 0 | return Error(Parser.getTok().getLoc(), |
1541 | 0 | "unexpected token, expected end of statement"); |
1542 | | |
1543 | 0 | clearFeatureBits(RISCV::FeatureRelax, "relax"); |
1544 | 0 | return false; |
1545 | 0 | } |
1546 | | |
1547 | | // Unknown option. |
1548 | 2 | Warning(Parser.getTok().getLoc(), |
1549 | 2 | "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or " |
1550 | 2 | "'norelax'"); |
1551 | 2 | Parser.eatToEndOfStatement(); |
1552 | 2 | return false; |
1553 | 2 | } |
1554 | | |
1555 | 1.09k | void RISCVAsmParser::emitToStreamer(MCStreamer &S, MCInst &Inst) { |
1556 | 1.09k | MCInst CInst; |
1557 | 1.09k | bool Res = compressInst(CInst, Inst, getSTI(), S.getContext()); |
1558 | 1.09k | CInst.setLoc(Inst.getLoc()); |
1559 | 1.09k | unsigned int ErrorCode = 0; |
1560 | 1.09k | S.EmitInstruction((Res ? CInst : Inst), getSTI(),ErrorCode); |
1561 | 1.09k | } |
1562 | | |
1563 | | void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value, |
1564 | 0 | MCStreamer &Out) { |
1565 | 0 | RISCVMatInt::InstSeq Seq; |
1566 | 0 | RISCVMatInt::generateInstSeq(Value, isRV64(), Seq); |
1567 | |
|
1568 | 0 | unsigned SrcReg = RISCV::X0; |
1569 | 0 | for (RISCVMatInt::Inst &Inst : Seq) { |
1570 | 0 | if (Inst.Opc == RISCV::LUI) { |
1571 | 0 | emitToStreamer( |
1572 | 0 | Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm)); |
1573 | 0 | } else { |
1574 | 0 | emitToStreamer( |
1575 | 0 | Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm( |
1576 | 0 | Inst.Imm)); |
1577 | 0 | } |
1578 | | |
1579 | | // Only the first instruction has X0 as its source. |
1580 | 0 | SrcReg = DestReg; |
1581 | 0 | } |
1582 | 0 | } |
1583 | | |
1584 | | void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, |
1585 | | const MCExpr *Symbol, |
1586 | | RISCVMCExpr::VariantKind VKHi, |
1587 | | unsigned SecondOpcode, SMLoc IDLoc, |
1588 | 0 | MCStreamer &Out) { |
1589 | | // A pair of instructions for PC-relative addressing; expands to |
1590 | | // TmpLabel: AUIPC TmpReg, VKHi(symbol) |
1591 | | // OP DestReg, TmpReg, %pcrel_lo(TmpLabel) |
1592 | 0 | MCContext &Ctx = getContext(); |
1593 | |
|
1594 | 0 | MCSymbol *TmpLabel = Ctx.createTempSymbol( |
1595 | 0 | "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false); |
1596 | 0 | Out.EmitLabel(TmpLabel); |
1597 | |
|
1598 | 0 | const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx); |
1599 | 0 | emitToStreamer( |
1600 | 0 | Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi)); |
1601 | |
|
1602 | 0 | const MCExpr *RefToLinkTmpLabel = |
1603 | 0 | RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx), |
1604 | 0 | RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx); |
1605 | |
|
1606 | 0 | emitToStreamer(Out, MCInstBuilder(SecondOpcode) |
1607 | 0 | .addOperand(DestReg) |
1608 | 0 | .addOperand(TmpReg) |
1609 | 0 | .addExpr(RefToLinkTmpLabel)); |
1610 | 0 | } |
1611 | | |
1612 | | void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, |
1613 | 0 | MCStreamer &Out) { |
1614 | | // The load local address pseudo-instruction "lla" is used in PC-relative |
1615 | | // addressing of local symbols: |
1616 | | // lla rdest, symbol |
1617 | | // expands to |
1618 | | // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) |
1619 | | // ADDI rdest, rdest, %pcrel_lo(TmpLabel) |
1620 | 0 | MCOperand DestReg = Inst.getOperand(0); |
1621 | 0 | const MCExpr *Symbol = Inst.getOperand(1).getExpr(); |
1622 | 0 | emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, |
1623 | 0 | RISCV::ADDI, IDLoc, Out); |
1624 | 0 | } |
1625 | | |
1626 | | void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc, |
1627 | 0 | MCStreamer &Out) { |
1628 | | // The load address pseudo-instruction "la" is used in PC-relative and |
1629 | | // GOT-indirect addressing of global symbols: |
1630 | | // la rdest, symbol |
1631 | | // expands to either (for non-PIC) |
1632 | | // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) |
1633 | | // ADDI rdest, rdest, %pcrel_lo(TmpLabel) |
1634 | | // or (for PIC) |
1635 | | // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol) |
1636 | | // Lx rdest, %pcrel_lo(TmpLabel)(rdest) |
1637 | 0 | MCOperand DestReg = Inst.getOperand(0); |
1638 | 0 | const MCExpr *Symbol = Inst.getOperand(1).getExpr(); |
1639 | 0 | unsigned SecondOpcode; |
1640 | 0 | RISCVMCExpr::VariantKind VKHi; |
1641 | | // FIXME: Should check .option (no)pic when implemented |
1642 | 0 | if (getContext().getObjectFileInfo()->isPositionIndependent()) { |
1643 | 0 | SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; |
1644 | 0 | VKHi = RISCVMCExpr::VK_RISCV_GOT_HI; |
1645 | 0 | } else { |
1646 | 0 | SecondOpcode = RISCV::ADDI; |
1647 | 0 | VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI; |
1648 | 0 | } |
1649 | 0 | emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out); |
1650 | 0 | } |
1651 | | |
1652 | | void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, |
1653 | 0 | MCStreamer &Out) { |
1654 | | // The load TLS IE address pseudo-instruction "la.tls.ie" is used in |
1655 | | // initial-exec TLS model addressing of global symbols: |
1656 | | // la.tls.ie rdest, symbol |
1657 | | // expands to |
1658 | | // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol) |
1659 | | // Lx rdest, %pcrel_lo(TmpLabel)(rdest) |
1660 | 0 | MCOperand DestReg = Inst.getOperand(0); |
1661 | 0 | const MCExpr *Symbol = Inst.getOperand(1).getExpr(); |
1662 | 0 | unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; |
1663 | 0 | emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI, |
1664 | 0 | SecondOpcode, IDLoc, Out); |
1665 | 0 | } |
1666 | | |
1667 | | void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, |
1668 | 0 | MCStreamer &Out) { |
1669 | | // The load TLS GD address pseudo-instruction "la.tls.gd" is used in |
1670 | | // global-dynamic TLS model addressing of global symbols: |
1671 | | // la.tls.gd rdest, symbol |
1672 | | // expands to |
1673 | | // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol) |
1674 | | // ADDI rdest, rdest, %pcrel_lo(TmpLabel) |
1675 | 0 | MCOperand DestReg = Inst.getOperand(0); |
1676 | 0 | const MCExpr *Symbol = Inst.getOperand(1).getExpr(); |
1677 | 0 | emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI, |
1678 | 0 | RISCV::ADDI, IDLoc, Out); |
1679 | 0 | } |
1680 | | |
1681 | | void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, |
1682 | | SMLoc IDLoc, MCStreamer &Out, |
1683 | 0 | bool HasTmpReg) { |
1684 | | // The load/store pseudo-instruction does a pc-relative load with |
1685 | | // a symbol. |
1686 | | // |
1687 | | // The expansion looks like this |
1688 | | // |
1689 | | // TmpLabel: AUIPC tmp, %pcrel_hi(symbol) |
1690 | | // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp) |
1691 | 0 | MCOperand DestReg = Inst.getOperand(0); |
1692 | 0 | unsigned SymbolOpIdx = HasTmpReg ? 2 : 1; |
1693 | 0 | unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0; |
1694 | 0 | MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx); |
1695 | 0 | const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr(); |
1696 | 0 | emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, |
1697 | 0 | Opcode, IDLoc, Out); |
1698 | 0 | } |
1699 | | |
1700 | | bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst, |
1701 | 0 | OperandVector &Operands) { |
1702 | 0 | assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction"); |
1703 | 0 | assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind"); |
1704 | 0 | if (Inst.getOperand(2).getReg() != RISCV::X4) { |
1705 | 0 | SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc(); |
1706 | 0 | return Error(ErrorLoc, "the second input operand must be tp/x4 when using " |
1707 | 0 | "%tprel_add modifier"); |
1708 | 0 | } |
1709 | | |
1710 | 0 | return false; |
1711 | 0 | } |
1712 | | |
1713 | | bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, |
1714 | | OperandVector &Operands, |
1715 | 1.09k | MCStreamer &Out) { |
1716 | 1.09k | Inst.setLoc(IDLoc); |
1717 | | |
1718 | 1.09k | switch (Inst.getOpcode()) { |
1719 | 1.09k | default: |
1720 | 1.09k | break; |
1721 | 1.09k | case RISCV::PseudoLI: { |
1722 | 0 | unsigned Reg = Inst.getOperand(0).getReg(); |
1723 | 0 | const MCOperand &Op1 = Inst.getOperand(1); |
1724 | 0 | if (Op1.isExpr()) { |
1725 | | // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar. |
1726 | | // Just convert to an addi. This allows compatibility with gas. |
1727 | 0 | emitToStreamer(Out, MCInstBuilder(RISCV::ADDI) |
1728 | 0 | .addReg(Reg) |
1729 | 0 | .addReg(RISCV::X0) |
1730 | 0 | .addExpr(Op1.getExpr())); |
1731 | 0 | return false; |
1732 | 0 | } |
1733 | 0 | int64_t Imm = Inst.getOperand(1).getImm(); |
1734 | | // On RV32 the immediate here can either be a signed or an unsigned |
1735 | | // 32-bit number. Sign extension has to be performed to ensure that Imm |
1736 | | // represents the expected signed 64-bit number. |
1737 | 0 | if (!isRV64()) |
1738 | 0 | Imm = SignExtend64<32>(Imm); |
1739 | 0 | emitLoadImm(Reg, Imm, Out); |
1740 | 0 | return false; |
1741 | 0 | } |
1742 | 0 | case RISCV::PseudoLLA: |
1743 | 0 | emitLoadLocalAddress(Inst, IDLoc, Out); |
1744 | 0 | return false; |
1745 | 0 | case RISCV::PseudoLA: |
1746 | 0 | emitLoadAddress(Inst, IDLoc, Out); |
1747 | 0 | return false; |
1748 | 0 | case RISCV::PseudoLA_TLS_IE: |
1749 | 0 | emitLoadTLSIEAddress(Inst, IDLoc, Out); |
1750 | 0 | return false; |
1751 | 0 | case RISCV::PseudoLA_TLS_GD: |
1752 | 0 | emitLoadTLSGDAddress(Inst, IDLoc, Out); |
1753 | 0 | return false; |
1754 | 0 | case RISCV::PseudoLB: |
1755 | 0 | emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false); |
1756 | 0 | return false; |
1757 | 0 | case RISCV::PseudoLBU: |
1758 | 0 | emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false); |
1759 | 0 | return false; |
1760 | 0 | case RISCV::PseudoLH: |
1761 | 0 | emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false); |
1762 | 0 | return false; |
1763 | 0 | case RISCV::PseudoLHU: |
1764 | 0 | emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false); |
1765 | 0 | return false; |
1766 | 0 | case RISCV::PseudoLW: |
1767 | 0 | emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false); |
1768 | 0 | return false; |
1769 | 0 | case RISCV::PseudoLWU: |
1770 | 0 | emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false); |
1771 | 0 | return false; |
1772 | 0 | case RISCV::PseudoLD: |
1773 | 0 | emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false); |
1774 | 0 | return false; |
1775 | 0 | case RISCV::PseudoFLW: |
1776 | 0 | emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true); |
1777 | 0 | return false; |
1778 | 0 | case RISCV::PseudoFLD: |
1779 | 0 | emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true); |
1780 | 0 | return false; |
1781 | 0 | case RISCV::PseudoSB: |
1782 | 0 | emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true); |
1783 | 0 | return false; |
1784 | 0 | case RISCV::PseudoSH: |
1785 | 0 | emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true); |
1786 | 0 | return false; |
1787 | 0 | case RISCV::PseudoSW: |
1788 | 0 | emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true); |
1789 | 0 | return false; |
1790 | 0 | case RISCV::PseudoSD: |
1791 | 0 | emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true); |
1792 | 0 | return false; |
1793 | 0 | case RISCV::PseudoFSW: |
1794 | 0 | emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true); |
1795 | 0 | return false; |
1796 | 0 | case RISCV::PseudoFSD: |
1797 | 0 | emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); |
1798 | 0 | return false; |
1799 | 0 | case RISCV::PseudoAddTPRel: |
1800 | 0 | if (checkPseudoAddTPRel(Inst, Operands)) |
1801 | 0 | return true; |
1802 | 0 | break; |
1803 | 1.09k | } |
1804 | | |
1805 | 1.09k | emitToStreamer(Out, Inst); |
1806 | 1.09k | return false; |
1807 | 1.09k | } |
1808 | | |
1809 | 26 | extern "C" void LLVMInitializeRISCVAsmParser() { |
1810 | 26 | RegisterMCAsmParser<RISCVAsmParser> X(TheRISCV32Target); |
1811 | 26 | RegisterMCAsmParser<RISCVAsmParser> Y(TheRISCV64Target); |
1812 | 26 | } |