xref: /freebsd/contrib/llvm-project/llvm/include/llvm/MC/MCExpr.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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