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