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/Compiler.h" 14 #include "llvm/Support/SMLoc.h" 15 #include <cstdint> 16 17 namespace llvm { 18 19 class MCAsmInfo; 20 class MCAssembler; 21 class MCContext; 22 class MCFixup; 23 class MCFragment; 24 class MCSection; 25 class MCStreamer; 26 class MCSymbol; 27 class MCValue; 28 class raw_ostream; 29 class StringRef; 30 class MCSymbolRefExpr; 31 32 /// Base class for the full range of assembler expressions which are 33 /// needed for parsing. 34 class MCExpr { 35 public: 36 // Allow MC classes to access the private `print` function. 37 friend class MCAsmInfo; 38 friend class MCFragment; 39 friend class MCOperand; 40 enum ExprKind : uint8_t { 41 Binary, ///< Binary expressions. 42 Constant, ///< Constant expressions. 43 SymbolRef, ///< References to labels and assigned expressions. 44 Unary, ///< Unary expressions. 45 Specifier, ///< Expression with a relocation specifier. 46 Target ///< Target specific expression. 47 }; 48 49 private: 50 static const unsigned NumSubclassDataBits = 24; 51 static_assert( 52 NumSubclassDataBits == CHAR_BIT * (sizeof(unsigned) - sizeof(ExprKind)), 53 "ExprKind and SubclassData together should take up one word"); 54 55 ExprKind Kind; 56 /// Field reserved for use by MCExpr subclasses. 57 unsigned SubclassData : NumSubclassDataBits; 58 SMLoc Loc; 59 60 void print(raw_ostream &OS, const MCAsmInfo *MAI, 61 int SurroundingPrec = 0) const; 62 bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 63 bool InSet) const; 64 65 protected: 66 using Spec = uint16_t; 67 explicit MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData = 0) Kind(Kind)68 : Kind(Kind), SubclassData(SubclassData), Loc(Loc) { 69 assert(SubclassData < (1 << NumSubclassDataBits) && 70 "Subclass data too large"); 71 } 72 73 LLVM_ABI bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 74 bool InSet) const; 75 getSubclassData()76 unsigned getSubclassData() const { return SubclassData; } 77 78 public: 79 MCExpr(const MCExpr &) = delete; 80 MCExpr &operator=(const MCExpr &) = delete; 81 82 /// \name Accessors 83 /// @{ 84 getKind()85 ExprKind getKind() const { return Kind; } getLoc()86 SMLoc getLoc() const { return Loc; } 87 88 /// @} 89 /// \name Utility Methods 90 /// @{ 91 92 LLVM_ABI void dump() const; 93 94 /// @} 95 /// \name Expression Evaluation 96 /// @{ 97 98 /// Try to evaluate the expression to an absolute value. 99 /// 100 /// \param Res - The absolute value, if evaluation succeeds. 101 /// \return - True on success. 102 LLVM_ABI bool evaluateAsAbsolute(int64_t &Res) const; 103 LLVM_ABI bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; 104 LLVM_ABI bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const; 105 106 /// Aggressive variant of evaluateAsRelocatable when relocations are 107 /// unavailable (e.g. .fill). Expects callers to handle errors when true is 108 /// returned. 109 LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, 110 const MCAssembler &Asm) const; 111 112 /// Try to evaluate the expression to a relocatable value, i.e. an 113 /// expression of the fixed form (a - b + constant). 114 /// 115 /// \param Res - The relocatable value, if evaluation succeeds. 116 /// \param Asm - The assembler object to use for evaluating values. 117 /// \return - True on success. 118 LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, 119 const MCAssembler *Asm) const; 120 121 /// Try to evaluate the expression to the form (a - b + constant) where 122 /// neither a nor b are variables. 123 /// 124 /// This is a more aggressive variant of evaluateAsRelocatable. The intended 125 /// use is for when relocations are not available, like the .size directive. 126 LLVM_ABI bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const; 127 128 /// Find the "associated section" for this expression, which is 129 /// currently defined as the absolute section for constants, or 130 /// otherwise the section associated with the first defined symbol in the 131 /// expression. 132 LLVM_ABI MCFragment *findAssociatedFragment() const; 133 134 /// @} 135 136 LLVM_ABI static bool evaluateSymbolicAdd(const MCAssembler *, bool, 137 const MCValue &, const MCValue &, 138 MCValue &); 139 }; 140 141 //// Represent a constant integer expression. 142 class MCConstantExpr : public MCExpr { 143 int64_t Value; 144 145 // Subclass data stores SizeInBytes in bits 0..7 and PrintInHex in bit 8. 146 static const unsigned SizeInBytesBits = 8; 147 static const unsigned SizeInBytesMask = (1 << SizeInBytesBits) - 1; 148 static const unsigned PrintInHexBit = 1 << SizeInBytesBits; 149 encodeSubclassData(bool PrintInHex,unsigned SizeInBytes)150 static unsigned encodeSubclassData(bool PrintInHex, unsigned SizeInBytes) { 151 assert(SizeInBytes <= sizeof(int64_t) && "Excessive size"); 152 return SizeInBytes | (PrintInHex ? PrintInHexBit : 0); 153 } 154 MCConstantExpr(int64_t Value,bool PrintInHex,unsigned SizeInBytes)155 MCConstantExpr(int64_t Value, bool PrintInHex, unsigned SizeInBytes) 156 : MCExpr(MCExpr::Constant, SMLoc(), 157 encodeSubclassData(PrintInHex, SizeInBytes)), Value(Value) {} 158 159 public: 160 /// \name Construction 161 /// @{ 162 163 LLVM_ABI static const MCConstantExpr *create(int64_t Value, MCContext &Ctx, 164 bool PrintInHex = false, 165 unsigned SizeInBytes = 0); 166 167 /// @} 168 /// \name Accessors 169 /// @{ 170 getValue()171 int64_t getValue() const { return Value; } getSizeInBytes()172 unsigned getSizeInBytes() const { 173 return getSubclassData() & SizeInBytesMask; 174 } 175 useHexFormat()176 bool useHexFormat() const { return (getSubclassData() & PrintInHexBit) != 0; } 177 178 /// @} 179 classof(const MCExpr * E)180 static bool classof(const MCExpr *E) { 181 return E->getKind() == MCExpr::Constant; 182 } 183 }; 184 185 /// Represent a reference to a symbol from inside an expression. 186 /// 187 /// A symbol reference in an expression may be a use of a label, a use of an 188 /// assembler variable (defined constant), or constitute an implicit definition 189 /// of the symbol as external. 190 class MCSymbolRefExpr : public MCExpr { 191 public: 192 // VariantKind isn't ideal for encoding relocation operators because: 193 // (a) other expressions, like MCConstantExpr (e.g., 4@l) and MCBinaryExpr 194 // (e.g., (a+1)@l), also need it; (b) semantics become unclear (e.g., folding 195 // expressions with @). MCSpecifierExpr, as used by AArch64 and RISC-V, offers 196 // a cleaner approach. 197 enum VariantKind : uint16_t { 198 VK_COFF_IMGREL32 = 3, // symbol@imgrel (image-relative) 199 200 FirstTargetSpecifier, 201 }; 202 203 private: 204 /// The symbol being referenced. 205 const MCSymbol *Symbol; 206 207 explicit MCSymbolRefExpr(const MCSymbol *Symbol, Spec specifier, 208 const MCAsmInfo *MAI, SMLoc Loc = SMLoc()); 209 210 public: 211 /// \name Construction 212 /// @{ 213 214 static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx, 215 SMLoc Loc = SMLoc()) { 216 return MCSymbolRefExpr::create(Symbol, 0, Ctx, Loc); 217 } 218 219 LLVM_ABI static const MCSymbolRefExpr *create(const MCSymbol *Symbol, 220 Spec specifier, MCContext &Ctx, 221 SMLoc Loc = SMLoc()); 222 223 /// @} 224 /// \name Accessors 225 /// @{ 226 getSymbol()227 const MCSymbol &getSymbol() const { return *Symbol; } 228 229 // Some targets encode the relocation specifier within SymA using 230 // MCSymbolRefExpr::SubclassData, which is copied to MCValue::Specifier, 231 // though this method is now deprecated. getKind()232 VariantKind getKind() const { return VariantKind(getSubclassData()); } getSpecifier()233 uint16_t getSpecifier() const { return getSubclassData(); } 234 235 /// @} 236 classof(const MCExpr * E)237 static bool classof(const MCExpr *E) { 238 return E->getKind() == MCExpr::SymbolRef; 239 } 240 }; 241 242 /// Unary assembler expressions. 243 class MCUnaryExpr : public MCExpr { 244 public: 245 enum Opcode { 246 LNot, ///< Logical negation. 247 Minus, ///< Unary minus. 248 Not, ///< Bitwise negation. 249 Plus ///< Unary plus. 250 }; 251 252 private: 253 const MCExpr *Expr; 254 MCUnaryExpr(Opcode Op,const MCExpr * Expr,SMLoc Loc)255 MCUnaryExpr(Opcode Op, const MCExpr *Expr, SMLoc Loc) 256 : MCExpr(MCExpr::Unary, Loc, Op), Expr(Expr) {} 257 258 public: 259 /// \name Construction 260 /// @{ 261 262 LLVM_ABI static const MCUnaryExpr * 263 create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()); 264 265 static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { 266 return create(LNot, Expr, Ctx, Loc); 267 } 268 269 static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { 270 return create(Minus, Expr, Ctx, Loc); 271 } 272 273 static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { 274 return create(Not, Expr, Ctx, Loc); 275 } 276 277 static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc = SMLoc()) { 278 return create(Plus, Expr, Ctx, Loc); 279 } 280 281 /// @} 282 /// \name Accessors 283 /// @{ 284 285 /// Get the kind of this unary expression. getOpcode()286 Opcode getOpcode() const { return (Opcode)getSubclassData(); } 287 288 /// Get the child of this unary expression. getSubExpr()289 const MCExpr *getSubExpr() const { return Expr; } 290 291 /// @} 292 classof(const MCExpr * E)293 static bool classof(const MCExpr *E) { 294 return E->getKind() == MCExpr::Unary; 295 } 296 }; 297 298 /// Binary assembler expressions. 299 class MCBinaryExpr : public MCExpr { 300 public: 301 enum Opcode { 302 Add, ///< Addition. 303 And, ///< Bitwise and. 304 Div, ///< Signed division. 305 EQ, ///< Equality comparison. 306 GT, ///< Signed greater than comparison (result is either 0 or some 307 ///< target-specific non-zero value) 308 GTE, ///< Signed greater than or equal comparison (result is either 0 or 309 ///< some target-specific non-zero value). 310 LAnd, ///< Logical and. 311 LOr, ///< Logical or. 312 LT, ///< Signed less than comparison (result is either 0 or 313 ///< some target-specific non-zero value). 314 LTE, ///< Signed less than or equal comparison (result is either 0 or 315 ///< some target-specific non-zero value). 316 Mod, ///< Signed remainder. 317 Mul, ///< Multiplication. 318 NE, ///< Inequality comparison. 319 Or, ///< Bitwise or. 320 OrNot, ///< Bitwise or not. 321 Shl, ///< Shift left. 322 AShr, ///< Arithmetic shift right. 323 LShr, ///< Logical shift right. 324 Sub, ///< Subtraction. 325 Xor ///< Bitwise exclusive or. 326 }; 327 328 private: 329 const MCExpr *LHS, *RHS; 330 331 MCBinaryExpr(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, 332 SMLoc Loc = SMLoc()) MCExpr(MCExpr::Binary,Loc,Op)333 : MCExpr(MCExpr::Binary, Loc, Op), LHS(LHS), RHS(RHS) {} 334 335 public: 336 /// \name Construction 337 /// @{ 338 339 LLVM_ABI static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS, 340 const MCExpr *RHS, MCContext &Ctx, 341 SMLoc Loc = SMLoc()); 342 343 static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS, 344 MCContext &Ctx, SMLoc Loc = SMLoc()) { 345 return create(Add, LHS, RHS, Ctx, Loc); 346 } 347 createAnd(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)348 static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS, 349 MCContext &Ctx) { 350 return create(And, LHS, RHS, Ctx); 351 } 352 createDiv(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)353 static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS, 354 MCContext &Ctx) { 355 return create(Div, LHS, RHS, Ctx); 356 } 357 createEQ(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)358 static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS, 359 MCContext &Ctx) { 360 return create(EQ, LHS, RHS, Ctx); 361 } 362 createGT(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)363 static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS, 364 MCContext &Ctx) { 365 return create(GT, LHS, RHS, Ctx); 366 } 367 createGTE(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)368 static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS, 369 MCContext &Ctx) { 370 return create(GTE, LHS, RHS, Ctx); 371 } 372 createLAnd(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)373 static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS, 374 MCContext &Ctx) { 375 return create(LAnd, LHS, RHS, Ctx); 376 } 377 createLOr(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)378 static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS, 379 MCContext &Ctx) { 380 return create(LOr, LHS, RHS, Ctx); 381 } 382 createLT(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)383 static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS, 384 MCContext &Ctx) { 385 return create(LT, LHS, RHS, Ctx); 386 } 387 createLTE(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)388 static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS, 389 MCContext &Ctx) { 390 return create(LTE, LHS, RHS, Ctx); 391 } 392 createMod(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)393 static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS, 394 MCContext &Ctx) { 395 return create(Mod, LHS, RHS, Ctx); 396 } 397 createMul(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)398 static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS, 399 MCContext &Ctx) { 400 return create(Mul, LHS, RHS, Ctx); 401 } 402 createNE(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)403 static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS, 404 MCContext &Ctx) { 405 return create(NE, LHS, RHS, Ctx); 406 } 407 createOr(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)408 static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS, 409 MCContext &Ctx) { 410 return create(Or, LHS, RHS, Ctx); 411 } 412 createShl(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)413 static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS, 414 MCContext &Ctx) { 415 return create(Shl, LHS, RHS, Ctx); 416 } 417 createAShr(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)418 static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS, 419 MCContext &Ctx) { 420 return create(AShr, LHS, RHS, Ctx); 421 } 422 createLShr(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)423 static const MCBinaryExpr *createLShr(const MCExpr *LHS, const MCExpr *RHS, 424 MCContext &Ctx) { 425 return create(LShr, LHS, RHS, Ctx); 426 } 427 createSub(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)428 static const MCBinaryExpr *createSub(const MCExpr *LHS, const MCExpr *RHS, 429 MCContext &Ctx) { 430 return create(Sub, LHS, RHS, Ctx); 431 } 432 createXor(const MCExpr * LHS,const MCExpr * RHS,MCContext & Ctx)433 static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS, 434 MCContext &Ctx) { 435 return create(Xor, LHS, RHS, Ctx); 436 } 437 438 /// @} 439 /// \name Accessors 440 /// @{ 441 442 /// Get the kind of this binary expression. getOpcode()443 Opcode getOpcode() const { return (Opcode)getSubclassData(); } 444 445 /// Get the left-hand side expression of the binary operator. getLHS()446 const MCExpr *getLHS() const { return LHS; } 447 448 /// Get the right-hand side expression of the binary operator. getRHS()449 const MCExpr *getRHS() const { return RHS; } 450 451 /// @} 452 classof(const MCExpr * E)453 static bool classof(const MCExpr *E) { 454 return E->getKind() == MCExpr::Binary; 455 } 456 }; 457 458 /// Extension point for target-specific MCExpr subclasses to implement. 459 /// This can encode a relocation operator, serving as a replacement for 460 /// MCSymbolRefExpr::VariantKind. Ideally, limit this to 461 /// top-level use, avoiding its inclusion as a subexpression. 462 /// 463 /// NOTE: All subclasses are required to have trivial destructors because 464 /// MCExprs are bump pointer allocated and not destructed. 465 class LLVM_ABI MCTargetExpr : public MCExpr { 466 virtual void anchor(); 467 468 protected: MCTargetExpr()469 MCTargetExpr() : MCExpr(Target, SMLoc()) {} 470 virtual ~MCTargetExpr() = default; 471 472 public: 473 virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0; 474 virtual bool evaluateAsRelocatableImpl(MCValue &Res, 475 const MCAssembler *Asm) const = 0; 476 // allow Target Expressions to be checked for equality isEqualTo(const MCExpr * x)477 virtual bool isEqualTo(const MCExpr *x) const { return false; } 478 // This should be set when assigned expressions are not valid ".set" 479 // expressions, e.g. registers, and must be inlined. inlineAssignedExpr()480 virtual bool inlineAssignedExpr() const { return false; } 481 virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; 482 virtual MCFragment *findAssociatedFragment() const = 0; 483 classof(const MCExpr * E)484 static bool classof(const MCExpr *E) { 485 return E->getKind() == MCExpr::Target; 486 } 487 }; 488 489 /// Extension point for target-specific MCExpr subclasses with a relocation 490 /// specifier, serving as a replacement for MCSymbolRefExpr::VariantKind. 491 /// Limit this to top-level use, avoiding its inclusion as a subexpression. 492 /// 493 /// NOTE: All subclasses are required to have trivial destructors because 494 /// MCExprs are bump pointer allocated and not destructed. 495 class LLVM_ABI MCSpecifierExpr : public MCExpr { 496 protected: 497 const MCExpr *Expr; 498 499 explicit MCSpecifierExpr(const MCExpr *Expr, Spec S, SMLoc Loc = SMLoc()) MCExpr(Specifier,Loc,S)500 : MCExpr(Specifier, Loc, S), Expr(Expr) {} 501 502 public: 503 static const MCSpecifierExpr *create(const MCExpr *Expr, Spec S, 504 MCContext &Ctx, SMLoc Loc = SMLoc()); 505 static const MCSpecifierExpr *create(const MCSymbol *Sym, Spec S, 506 MCContext &Ctx, SMLoc Loc = SMLoc()); 507 getSpecifier()508 Spec getSpecifier() const { return getSubclassData(); } getSubExpr()509 const MCExpr *getSubExpr() const { return Expr; } 510 classof(const MCExpr * E)511 static bool classof(const MCExpr *E) { 512 return E->getKind() == MCExpr::Specifier; 513 } 514 }; 515 516 } // end namespace llvm 517 518 #endif // LLVM_MC_MCEXPR_H 519