1 | //===- MCExpr.h - Assembly Level Expressions --------------------*- C++ -*-===// |
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 | #ifndef LLVM_MC_MCEXPR_H |
10 | #define LLVM_MC_MCEXPR_H |
11 | |
12 | #include "llvm/ADT/DenseMap.h" |
13 | #include "llvm/Support/SMLoc.h" |
14 | #include <cstdint> |
15 | |
16 | namespace llvm { |
17 | |
18 | class MCAsmInfo; |
19 | class MCAssembler; |
20 | class MCContext; |
21 | class MCFixup; |
22 | class MCFragment; |
23 | class MCSection; |
24 | class MCStreamer; |
25 | class MCSymbol; |
26 | class MCValue; |
27 | class raw_ostream; |
28 | class StringRef; |
29 | |
30 | using SectionAddrMap = DenseMap<const MCSection *, uint64_t>; |
31 | |
32 | /// Base class for the full range of assembler expressions which are |
33 | /// needed for parsing. |
34 | class MCExpr { |
35 | public: |
36 | enum ExprKind : uint8_t { |
37 | Binary, ///< Binary expressions. |
38 | Constant, ///< Constant expressions. |
39 | SymbolRef, ///< References to labels and assigned expressions. |
40 | Unary, ///< Unary expressions. |
41 | Target ///< Target specific expression. |
42 | }; |
43 | |
44 | private: |
45 | static const unsigned NumSubclassDataBits = 24; |
46 | static_assert( |
47 | NumSubclassDataBits == CHAR_BIT * (sizeof(unsigned) - sizeof(ExprKind)), |
48 | "ExprKind and SubclassData together should take up one word" ); |
49 | |
50 | ExprKind Kind; |
51 | /// Field reserved for use by MCExpr subclasses. |
52 | unsigned SubclassData : NumSubclassDataBits; |
53 | SMLoc Loc; |
54 | |
55 | bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, |
56 | const SectionAddrMap *Addrs, bool InSet) const; |
57 | |
58 | protected: |
59 | explicit MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData = 0) |
60 | : Kind(Kind), SubclassData(SubclassData), Loc(Loc) { |
61 | assert(SubclassData < (1 << NumSubclassDataBits) && |
62 | "Subclass data too large" ); |
63 | } |
64 | |
65 | bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, |
66 | const MCFixup *Fixup, |
67 | const SectionAddrMap *Addrs, bool InSet) const; |
68 | |
69 | unsigned getSubclassData() const { return SubclassData; } |
70 | |
71 | public: |
72 | MCExpr(const MCExpr &) = delete; |
73 | MCExpr &operator=(const MCExpr &) = delete; |
74 | |
75 | /// \name Accessors |
76 | /// @{ |
77 | |
78 | ExprKind getKind() const { return Kind; } |
79 | SMLoc getLoc() const { return Loc; } |
80 | |
81 | /// @} |
82 | /// \name Utility Methods |
83 | /// @{ |
84 | |
85 | void print(raw_ostream &OS, const MCAsmInfo *MAI, |
86 | bool InParens = false) const; |
87 | void dump() const; |
88 | |
89 | /// @} |
90 | /// \name Expression Evaluation |
91 | /// @{ |
92 | |
93 | /// Try to evaluate the expression to an absolute value. |
94 | /// |
95 | /// \param Res - The absolute value, if evaluation succeeds. |
96 | /// \return - True on success. |
97 | bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm, |
98 | const SectionAddrMap &Addrs) const; |
99 | bool evaluateAsAbsolute(int64_t &Res) const; |
100 | bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; |
101 | bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const; |
102 | |
103 | /// Aggressive variant of evaluateAsRelocatable when relocations are |
104 | /// unavailable (e.g. .fill). Expects callers to handle errors when true is |
105 | /// returned. |
106 | bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const; |
107 | |
108 | /// Try to evaluate the expression to a relocatable value, i.e. an |
109 | /// expression of the fixed form (a - b + constant). |
110 | /// |
111 | /// \param Res - The relocatable value, if evaluation succeeds. |
112 | /// \param Asm - The assembler object to use for evaluating values. |
113 | /// \param Fixup - The Fixup object if available. |
114 | /// \return - True on success. |
115 | bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, |
116 | const MCFixup *Fixup) const; |
117 | |
118 | /// Try to evaluate the expression to the form (a - b + constant) where |
119 | /// neither a nor b are variables. |
120 | /// |
121 | /// This is a more aggressive variant of evaluateAsRelocatable. The intended |
122 | /// use is for when relocations are not available, like the .size directive. |
123 | bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const; |
124 | |
125 | /// Find the "associated section" for this expression, which is |
126 | /// currently defined as the absolute section for constants, or |
127 | /// otherwise the section associated with the first defined symbol in the |
128 | /// expression. |
129 | MCFragment *findAssociatedFragment() const; |
130 | |
131 | /// @} |
132 | }; |
133 | |
134 | inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { |
135 | E.print(OS, MAI: nullptr); |
136 | return OS; |
137 | } |
138 | |
139 | //// Represent a constant integer expression. |
140 | class MCConstantExpr : public MCExpr { |
141 | int64_t Value; |
142 | |
143 | // Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8. |
144 | static const unsigned SizeInBytesBits = 8; |
145 | static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1; |
146 | static const unsigned PrintInHexBit = 1 << SizeInBytesBits; |
147 | |
148 | static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) { |
149 | assert(SizeInBytes <= sizeof(int64_t) && "Excessive size" ); |
150 | return SizeInBytes | (PrintInHex ? PrintInHexBit : 0); |
151 | } |
152 | |
153 | MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes) |
154 | : MCExpr(MCExpr::Constant, SMLoc(), |
155 | encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {} |
156 | |
157 | public: |
158 | /// \name Construction |
159 | /// @{ |
160 | |
161 | static const MCConstantExpr *create(int64_t Value, MCContext &Ctx, |
162 | bool PrintInHex = false, |
163 | unsigned SizeInBytes = 0); |
164 | |
165 | /// @} |
166 | /// \name Accessors |
167 | /// @{ |
168 | |
169 | int64_t getValue() const { return Value; } |
170 | unsigned getSizeInBytes() const { |
171 | return getSubclassData() & SizeInBytesMask; |
172 | } |
173 | |
174 | bool useHexFormat() const { return (getSubclassData() & PrintInHexBit) != 0; } |
175 | |
176 | /// @} |
177 | |
178 | static bool classof(const MCExpr *E) { |
179 | return E->getKind() == MCExpr::Constant; |
180 | } |
181 | }; |
182 | |
183 | /// Represent a reference to a symbol from inside an expression. |
184 | /// |
185 | /// A symbol reference in an expression may be a use of a label, a use of an |
186 | /// assembler variable (defined constant), or constitute an implicit definition |
187 | /// of the symbol as external. |
188 | class MCSymbolRefExpr : public MCExpr { |
189 | public: |
190 | enum VariantKind : uint16_t { |
191 | VK_None, |
192 | VK_Invalid, |
193 | |
194 | VK_GOT, |
195 | VK_GOTOFF, |
196 | VK_GOTREL, |
197 | VK_PCREL, |
198 | VK_GOTPCREL, |
199 | VK_GOTPCREL_NORELAX, |
200 | VK_GOTTPOFF, |
201 | VK_INDNTPOFF, |
202 | VK_NTPOFF, |
203 | VK_GOTNTPOFF, |
204 | VK_PLT, |
205 | VK_TLSGD, |
206 | VK_TLSLD, |
207 | VK_TLSLDM, |
208 | VK_TPOFF, |
209 | VK_DTPOFF, |
210 | VK_TLSCALL, // symbol(tlscall) |
211 | VK_TLSDESC, // symbol(tlsdesc) |
212 | VK_TLVP, // Mach-O thread local variable relocations |
213 | VK_TLVPPAGE, |
214 | VK_TLVPPAGEOFF, |
215 | VK_PAGE, |
216 | VK_PAGEOFF, |
217 | VK_GOTPAGE, |
218 | VK_GOTPAGEOFF, |
219 | VK_SECREL, |
220 | VK_SIZE, // symbol@SIZE |
221 | VK_WEAKREF, // The link between the symbols in .weakref foo, bar |
222 | VK_FUNCDESC, |
223 | VK_GOTFUNCDESC, |
224 | VK_GOTOFFFUNCDESC, |
225 | VK_TLSGD_FDPIC, |
226 | VK_TLSLDM_FDPIC, |
227 | VK_GOTTPOFF_FDPIC, |
228 | |
229 | VK_X86_ABS8, |
230 | VK_X86_PLTOFF, |
231 | |
232 | VK_ARM_NONE, |
233 | VK_ARM_GOT_PREL, |
234 | VK_ARM_TARGET1, |
235 | VK_ARM_TARGET2, |
236 | VK_ARM_PREL31, |
237 | VK_ARM_SBREL, // symbol(sbrel) |
238 | VK_ARM_TLSLDO, // symbol(tlsldo) |
239 | VK_ARM_TLSDESCSEQ, |
240 | |
241 | VK_AVR_NONE, |
242 | VK_AVR_LO8, |
243 | VK_AVR_HI8, |
244 | VK_AVR_HLO8, |
245 | VK_AVR_DIFF8, |
246 | VK_AVR_DIFF16, |
247 | VK_AVR_DIFF32, |
248 | VK_AVR_PM, |
249 | |
250 | VK_PPC_LO, // symbol@l |
251 | VK_PPC_HI, // symbol@h |
252 | VK_PPC_HA, // symbol@ha |
253 | VK_PPC_HIGH, // symbol@high |
254 | VK_PPC_HIGHA, // symbol@higha |
255 | VK_PPC_HIGHER, // symbol@higher |
256 | VK_PPC_HIGHERA, // symbol@highera |
257 | VK_PPC_HIGHEST, // symbol@highest |
258 | VK_PPC_HIGHESTA, // symbol@highesta |
259 | VK_PPC_GOT_LO, // symbol@got@l |
260 | VK_PPC_GOT_HI, // symbol@got@h |
261 | VK_PPC_GOT_HA, // symbol@got@ha |
262 | VK_PPC_TOCBASE, // symbol@tocbase |
263 | VK_PPC_TOC, // symbol@toc |
264 | VK_PPC_TOC_LO, // symbol@toc@l |
265 | VK_PPC_TOC_HI, // symbol@toc@h |
266 | VK_PPC_TOC_HA, // symbol@toc@ha |
267 | VK_PPC_U, // symbol@u |
268 | VK_PPC_L, // symbol@l |
269 | VK_PPC_DTPMOD, // symbol@dtpmod |
270 | VK_PPC_TPREL_LO, // symbol@tprel@l |
271 | VK_PPC_TPREL_HI, // symbol@tprel@h |
272 | VK_PPC_TPREL_HA, // symbol@tprel@ha |
273 | VK_PPC_TPREL_HIGH, // symbol@tprel@high |
274 | VK_PPC_TPREL_HIGHA, // symbol@tprel@higha |
275 | VK_PPC_TPREL_HIGHER, // symbol@tprel@higher |
276 | VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera |
277 | VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest |
278 | VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta |
279 | VK_PPC_DTPREL_LO, // symbol@dtprel@l |
280 | VK_PPC_DTPREL_HI, // symbol@dtprel@h |
281 | VK_PPC_DTPREL_HA, // symbol@dtprel@ha |
282 | VK_PPC_DTPREL_HIGH, // symbol@dtprel@high |
283 | VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha |
284 | VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher |
285 | VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera |
286 | VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest |
287 | VK_PPC_DTPREL_HIGHESTA, // symbol@dtprel@highesta |
288 | VK_PPC_GOT_TPREL, // symbol@got@tprel |
289 | VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l |
290 | VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h |
291 | VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha |
292 | VK_PPC_GOT_DTPREL, // symbol@got@dtprel |
293 | VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l |
294 | VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h |
295 | VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha |
296 | VK_PPC_TLS, // symbol@tls |
297 | VK_PPC_GOT_TLSGD, // symbol@got@tlsgd |
298 | VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l |
299 | VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h |
300 | VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha |
301 | VK_PPC_TLSGD, // symbol@tlsgd |
302 | VK_PPC_AIX_TLSGD, // symbol@gd |
303 | VK_PPC_AIX_TLSGDM, // symbol@m |
304 | VK_PPC_AIX_TLSIE, // symbol@ie |
305 | VK_PPC_AIX_TLSLE, // symbol@le |
306 | VK_PPC_AIX_TLSLD, // symbol@ld |
307 | VK_PPC_AIX_TLSML, // symbol@ml |
308 | VK_PPC_GOT_TLSLD, // symbol@got@tlsld |
309 | VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l |
310 | VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h |
311 | VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha |
312 | VK_PPC_GOT_PCREL, // symbol@got@pcrel |
313 | VK_PPC_GOT_TLSGD_PCREL, // symbol@got@tlsgd@pcrel |
314 | VK_PPC_GOT_TLSLD_PCREL, // symbol@got@tlsld@pcrel |
315 | VK_PPC_GOT_TPREL_PCREL, // symbol@got@tprel@pcrel |
316 | VK_PPC_TLS_PCREL, // symbol@tls@pcrel |
317 | VK_PPC_TLSLD, // symbol@tlsld |
318 | VK_PPC_LOCAL, // symbol@local |
319 | VK_PPC_NOTOC, // symbol@notoc |
320 | VK_PPC_PCREL_OPT, // .reloc expr, R_PPC64_PCREL_OPT, expr |
321 | |
322 | VK_COFF_IMGREL32, // symbol@imgrel (image-relative) |
323 | |
324 | VK_Hexagon_LO16, |
325 | VK_Hexagon_HI16, |
326 | VK_Hexagon_GPREL, |
327 | VK_Hexagon_GD_GOT, |
328 | VK_Hexagon_LD_GOT, |
329 | VK_Hexagon_GD_PLT, |
330 | VK_Hexagon_LD_PLT, |
331 | VK_Hexagon_IE, |
332 | VK_Hexagon_IE_GOT, |
333 | |
334 | VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature) |
335 | VK_WASM_TLSREL, // Memory address relative to __tls_base |
336 | VK_WASM_MBREL, // Memory address relative to __memory_base |
337 | VK_WASM_TBREL, // Table index relative to __table_base |
338 | VK_WASM_GOT_TLS, // Wasm global index of TLS symbol. |
339 | VK_WASM_FUNCINDEX, // Wasm function index. |
340 | |
341 | VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo |
342 | VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi |
343 | VK_AMDGPU_REL32_LO, // symbol@rel32@lo |
344 | VK_AMDGPU_REL32_HI, // symbol@rel32@hi |
345 | VK_AMDGPU_REL64, // symbol@rel64 |
346 | VK_AMDGPU_ABS32_LO, // symbol@abs32@lo |
347 | VK_AMDGPU_ABS32_HI, // symbol@abs32@hi |
348 | |
349 | VK_VE_HI32, // symbol@hi |
350 | VK_VE_LO32, // symbol@lo |
351 | VK_VE_PC_HI32, // symbol@pc_hi |
352 | VK_VE_PC_LO32, // symbol@pc_lo |
353 | VK_VE_GOT_HI32, // symbol@got_hi |
354 | VK_VE_GOT_LO32, // symbol@got_lo |
355 | VK_VE_GOTOFF_HI32, // symbol@gotoff_hi |
356 | VK_VE_GOTOFF_LO32, // symbol@gotoff_lo |
357 | VK_VE_PLT_HI32, // symbol@plt_hi |
358 | VK_VE_PLT_LO32, // symbol@plt_lo |
359 | VK_VE_TLS_GD_HI32, // symbol@tls_gd_hi |
360 | VK_VE_TLS_GD_LO32, // symbol@tls_gd_lo |
361 | VK_VE_TPOFF_HI32, // symbol@tpoff_hi |
362 | VK_VE_TPOFF_LO32, // symbol@tpoff_lo |
363 | |
364 | VK_TPREL, |
365 | VK_DTPREL |
366 | }; |
367 | |
368 | private: |
369 | /// The symbol being referenced. |
370 | const MCSymbol *Symbol; |
371 | |
372 | // Subclass data stores VariantKind in bits 0..15 and HasSubsectionsViaSymbols |
373 | // in bit 16. |
374 | static const unsigned VariantKindBits = 16; |
375 | static const unsigned VariantKindMask = (1 << VariantKindBits) - 1; |
376 | |
377 | // FIXME: Remove this bit. |
378 | static const unsigned HasSubsectionsViaSymbolsBit = 1 << VariantKindBits; |
379 | |
380 | static unsigned encodeSubclassData(VariantKind Kind, |
381 | bool HasSubsectionsViaSymbols) { |
382 | return (unsigned)Kind | |
383 | (HasSubsectionsViaSymbols ? HasSubsectionsViaSymbolsBit : 0); |
384 | } |
385 | |
386 | explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, |
387 | const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); |
388 | |
389 | public: |
390 | /// \name Construction |
391 | /// @{ |
392 | |
393 | static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx) { |
394 | return MCSymbolRefExpr::create(Symbol, Kind: VK_None, Ctx); |
395 | } |
396 | |
397 | static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind, |
398 | MCContext &Ctx, SMLoc Loc = SMLoc()); |
399 | static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind, |
400 | MCContext &Ctx); |
401 | |
402 | /// @} |
403 | /// \name Accessors |
404 | /// @{ |
405 | |
406 | const MCSymbol &getSymbol() const { return *Symbol; } |
407 | |
408 | VariantKind getKind() const { |
409 | return (VariantKind)(getSubclassData() & VariantKindMask); |
410 | } |
411 | |
412 | bool hasSubsectionsViaSymbols() const { |
413 | return (getSubclassData() & HasSubsectionsViaSymbolsBit) != 0; |
414 | } |
415 | |
416 | /// @} |
417 | /// \name Static Utility Functions |
418 | /// @{ |
419 | |
420 | static StringRef getVariantKindName(VariantKind Kind); |
421 | |
422 | static VariantKind getVariantKindForName(StringRef Name); |
423 | |
424 | /// @} |
425 | |
426 | static bool classof(const MCExpr *E) { |
427 | return E->getKind() == MCExpr::SymbolRef; |
428 | } |
429 | }; |
430 | |
431 | /// Unary assembler expressions. |
432 | class MCUnaryExpr : public MCExpr { |
433 | public: |
434 | enum Opcode { |
435 | LNot, ///< Logical negation. |
436 | Minus, ///< Unary minus. |
437 | Not, ///< Bitwise negation. |
438 | Plus ///< Unary plus. |
439 | }; |
440 | |
441 | private: |
442 | const MCExpr *Expr; |
443 | |
444 | MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) |
445 | : MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {} |
446 | |
447 | public: |
448 | /// \name Construction |
449 | /// @{ |
450 | |
451 | static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr, |
452 | MCContext &Ctx, SMLoc Loc = SMLoc()); |
453 | |
454 | static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { |
455 | return create(Op: LNot, Expr, Ctx, Loc); |
456 | } |
457 | |
458 | static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { |
459 | return create(Op: Minus, Expr, Ctx, Loc); |
460 | } |
461 | |
462 | static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { |
463 | return create(Op: Not, Expr, Ctx, Loc); |
464 | } |
465 | |
466 | static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { |
467 | return create(Op: Plus, Expr, Ctx, Loc); |
468 | } |
469 | |
470 | /// @} |
471 | /// \name Accessors |
472 | /// @{ |
473 | |
474 | /// Get the kind of this unary expression. |
475 | Opcode getOpcode() const { return (Opcode)getSubclassData(); } |
476 | |
477 | /// Get the child of this unary expression. |
478 | const MCExpr *getSubExpr() const { return Expr; } |
479 | |
480 | /// @} |
481 | |
482 | static bool classof(const MCExpr *E) { |
483 | return E->getKind() == MCExpr::Unary; |
484 | } |
485 | }; |
486 | |
487 | /// Binary assembler expressions. |
488 | class MCBinaryExpr : public MCExpr { |
489 | public: |
490 | enum Opcode { |
491 | Add, ///< Addition. |
492 | And, ///< Bitwise and. |
493 | Div, ///< Signed division. |
494 | EQ, ///< Equality comparison. |
495 | GT, ///< Signed greater than comparison (result is either 0 or some |
496 | ///< target-specific non-zero value) |
497 | GTE, ///< Signed greater than or equal comparison (result is either 0 or |
498 | ///< some target-specific non-zero value). |
499 | LAnd, ///< Logical and. |
500 | LOr, ///< Logical or. |
501 | LT, ///< Signed less than comparison (result is either 0 or |
502 | ///< some target-specific non-zero value). |
503 | LTE, ///< Signed less than or equal comparison (result is either 0 or |
504 | ///< some target-specific non-zero value). |
505 | Mod, ///< Signed remainder. |
506 | Mul, ///< Multiplication. |
507 | NE, ///< Inequality comparison. |
508 | Or, ///< Bitwise or. |
509 | OrNot, ///< Bitwise or not. |
510 | Shl, ///< Shift left. |
511 | AShr, ///< Arithmetic shift right. |
512 | LShr, ///< Logical shift right. |
513 | Sub, ///< Subtraction. |
514 | Xor ///< Bitwise exclusive or. |
515 | }; |
516 | |
517 | private: |
518 | const MCExpr *LHS, *RHS; |
519 | |
520 | MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, |
521 | SMLoc Loc = SMLoc()) |
522 | : MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {} |
523 | |
524 | public: |
525 | /// \name Construction |
526 | /// @{ |
527 | |
528 | static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS, |
529 | const MCExpr *RHS, MCContext &Ctx, |
530 | SMLoc Loc = SMLoc()); |
531 | |
532 | static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS, |
533 | MCContext &Ctx) { |
534 | return create(Op: Add, LHS, RHS, Ctx); |
535 | } |
536 | |
537 | static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS, |
538 | MCContext &Ctx) { |
539 | return create(Op: And, LHS, RHS, Ctx); |
540 | } |
541 | |
542 | static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS, |
543 | MCContext &Ctx) { |
544 | return create(Op: Div, LHS, RHS, Ctx); |
545 | } |
546 | |
547 | static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS, |
548 | MCContext &Ctx) { |
549 | return create(Op: EQ, LHS, RHS, Ctx); |
550 | } |
551 | |
552 | static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS, |
553 | MCContext &Ctx) { |
554 | return create(Op: GT, LHS, RHS, Ctx); |
555 | } |
556 | |
557 | static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS, |
558 | MCContext &Ctx) { |
559 | return create(Op: GTE, LHS, RHS, Ctx); |
560 | } |
561 | |
562 | static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS, |
563 | MCContext &Ctx) { |
564 | return create(Op: LAnd, LHS, RHS, Ctx); |
565 | } |
566 | |
567 | static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS, |
568 | MCContext &Ctx) { |
569 | return create(Op: LOr, LHS, RHS, Ctx); |
570 | } |
571 | |
572 | static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS, |
573 | MCContext &Ctx) { |
574 | return create(Op: LT, LHS, RHS, Ctx); |
575 | } |
576 | |
577 | static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS, |
578 | MCContext &Ctx) { |
579 | return create(Op: LTE, LHS, RHS, Ctx); |
580 | } |
581 | |
582 | static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS, |
583 | MCContext &Ctx) { |
584 | return create(Op: Mod, LHS, RHS, Ctx); |
585 | } |
586 | |
587 | static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS, |
588 | MCContext &Ctx) { |
589 | return create(Op: Mul, LHS, RHS, Ctx); |
590 | } |
591 | |
592 | static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS, |
593 | MCContext &Ctx) { |
594 | return create(Op: NE, LHS, RHS, Ctx); |
595 | } |
596 | |
597 | static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS, |
598 | MCContext &Ctx) { |
599 | return create(Op: Or, LHS, RHS, Ctx); |
600 | } |
601 | |
602 | static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS, |
603 | MCContext &Ctx) { |
604 | return create(Op: Shl, LHS, RHS, Ctx); |
605 | } |
606 | |
607 | static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS, |
608 | MCContext &Ctx) { |
609 | return create(Op: AShr, LHS, RHS, Ctx); |
610 | } |
611 | |
612 | static const MCBinaryExpr *createLShr(const MCExpr *LHS, const MCExpr *RHS, |
613 | MCContext &Ctx) { |
614 | return create(Op: LShr, LHS, RHS, Ctx); |
615 | } |
616 | |
617 | static const MCBinaryExpr *createSub(const MCExpr *LHS, const MCExpr *RHS, |
618 | MCContext &Ctx) { |
619 | return create(Op: Sub, LHS, RHS, Ctx); |
620 | } |
621 | |
622 | static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS, |
623 | MCContext &Ctx) { |
624 | return create(Op: Xor, LHS, RHS, Ctx); |
625 | } |
626 | |
627 | /// @} |
628 | /// \name Accessors |
629 | /// @{ |
630 | |
631 | /// Get the kind of this binary expression. |
632 | Opcode getOpcode() const { return (Opcode)getSubclassData(); } |
633 | |
634 | /// Get the left-hand side expression of the binary operator. |
635 | const MCExpr *getLHS() const { return LHS; } |
636 | |
637 | /// Get the right-hand side expression of the binary operator. |
638 | const MCExpr *getRHS() const { return RHS; } |
639 | |
640 | /// @} |
641 | |
642 | static bool classof(const MCExpr *E) { |
643 | return E->getKind() == MCExpr::Binary; |
644 | } |
645 | }; |
646 | |
647 | /// This is an extension point for target-specific MCExpr subclasses to |
648 | /// implement. |
649 | /// |
650 | /// NOTE: All subclasses are required to have trivial destructors because |
651 | /// MCExprs are bump pointer allocated and not destructed. |
652 | class MCTargetExpr : public MCExpr { |
653 | virtual void anchor(); |
654 | |
655 | protected: |
656 | MCTargetExpr() : MCExpr(Target, SMLoc()) {} |
657 | virtual ~MCTargetExpr() = default; |
658 | |
659 | public: |
660 | virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0; |
661 | virtual bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, |
662 | const MCFixup *Fixup) const = 0; |
663 | // allow Target Expressions to be checked for equality |
664 | virtual bool isEqualTo(const MCExpr *x) const { return false; } |
665 | // This should be set when assigned expressions are not valid ".set" |
666 | // expressions, e.g. registers, and must be inlined. |
667 | virtual bool inlineAssignedExpr() const { return false; } |
668 | virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; |
669 | virtual MCFragment *findAssociatedFragment() const = 0; |
670 | |
671 | virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; |
672 | |
673 | static bool classof(const MCExpr *E) { |
674 | return E->getKind() == MCExpr::Target; |
675 | } |
676 | }; |
677 | |
678 | } // end namespace llvm |
679 | |
680 | #endif // LLVM_MC_MCEXPR_H |
681 | |