12#include "llvm/Config/llvm-config.h"
31#define DEBUG_TYPE "mcexpr"
36STATISTIC(MCExprEvaluate,
"Number of MCExpr evaluations");
55 int SurroundingPrec)
const {
56 constexpr int MaxPrec = 9;
59 return cast<MCTargetExpr>(
this)->printImpl(
OS, MAI);
61 auto Value = cast<MCConstantExpr>(*this).getValue();
62 auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat();
63 auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes();
64 if (Value < 0 && MAI && !MAI->supportsSignedData())
67 switch (SizeInBytes) {
96 OS <<
"@<variant " <<
Kind <<
'>';
127 bool Paren = Prec < SurroundingPrec;
132 int SubPrec = Prec ? Prec : MaxPrec;
133 BE.
getLHS()->print(
OS, MAI, SubPrec);
139 if (RHSC->getValue() < 0) {
140 OS << RHSC->getValue();
170 BE.
getRHS()->print(
OS, MAI, SubPrec + 1);
177 auto &SE = cast<MCSpecifierExpr>(*
this);
182 OS <<
"specifier(" << SE.getSpecifier() <<
',';
183 SE.getSubExpr()->print(
OS,
nullptr);
192#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
194 print(
dbgs(),
nullptr);
214 unsigned SizeInBytes) {
220MCSymbolRefExpr::MCSymbolRefExpr(
const MCSymbol *Symbol,
Spec specifier,
222 :
MCExpr(
MCExpr::SymbolRef, Loc, specifier), Symbol(Symbol) {
234void MCTargetExpr::anchor() {}
238bool MCExpr::evaluateAsAbsolute(int64_t &Res)
const {
239 return evaluateAsAbsolute(Res,
nullptr,
false);
242bool MCExpr::evaluateAsAbsolute(int64_t &Res,
const MCAssembler &Asm)
const {
243 return evaluateAsAbsolute(Res, &Asm,
false);
246bool MCExpr::evaluateAsAbsolute(int64_t &Res,
const MCAssembler *Asm)
const {
247 return evaluateAsAbsolute(Res, Asm,
false);
251 return evaluateAsAbsolute(Res, &Asm,
true);
254bool MCExpr::evaluateAsAbsolute(int64_t &Res,
const MCAssembler *Asm,
260 Res = CE->getValue();
265 Res =
Value.getConstant();
269 return IsRelocatable &&
Value.isAbsolute() &&
Value.getSpecifier() == 0;
283 if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(SA, SB, InSet))
286 auto FinalizeFolding = [&]() {
289 if (Asm->isThumbFunc(&SA))
310 bool Layout = Asm->hasLayout();
314 if (FA == FB && !SA.
isVariable() && !SB.isVariable()) {
315 Addend += SA.
getOffset() - SB.getOffset();
316 return FinalizeFolding();
320 Addend += Asm->getSymbolOffset(SA) - Asm->getSymbolOffset(SB);
342 int64_t Displacement = SA.
getOffset() - SB.getOffset();
353 bool BBeforeRelax =
false, AAfterRelax =
false;
354 for (
auto F = FB;
F;
F =
F->getNext()) {
355 if (
F &&
F->isLinkerRelaxable()) {
356 if (&*
F != FB || SBOffset !=
F->getSize())
358 if (&*
F != FA || SAOffset ==
F->getSize())
360 if (BBeforeRelax && AAfterRelax)
366 Addend +=
Reverse ? -Displacement : Displacement;
373 Displacement +=
F->getFixedSize();
376 Asm->hasFinalLayout()) {
380 Displacement +=
F->getSize();
381 }
else if (
auto *FF = dyn_cast<MCFillFragment>(
F);
382 FF && FF->getNumValues().evaluateAsAbsolute(Num)) {
383 Displacement += Num * FF->getValueSize();
412 int64_t LHS_Cst =
LHS.getConstant();
416 int64_t RHS_Cst =
RHS.getConstant();
419 int64_t Result_Cst = LHS_Cst + RHS_Cst;
422 if (Asm && !
LHS.getSpecifier() && !
RHS.getSpecifier()) {
427 if (LHS_A && RHS_B) {
430 if (RHS_A && LHS_B) {
436 if ((LHS_A && RHS_A) || (LHS_B && RHS_B))
441 auto *
A = LHS_A ? LHS_A : RHS_A;
442 auto *
B = LHS_B ? LHS_B : RHS_B;
443 auto Spec =
LHS.getSpecifier();
459 ++stats::MCExprEvaluate;
462 return cast<MCTargetExpr>(
this)->evaluateAsRelocatableImpl(Res, Asm);
464 Res =
MCValue::get(cast<MCConstantExpr>(
this)->getValue());
470 const auto Kind = SRE->
getKind();
471 bool Layout = Asm && Asm->hasLayout();
477 if (
Sym.isResolving()) {
478 if (Asm && Asm->hasFinalLayout()) {
479 Asm->getContext().reportError(
480 Sym.getVariableValue()->getLoc(),
481 "cyclic dependency detected for symbol '" +
Sym.getName() +
"'");
486 if (
Sym.isVariable() && (Kind == 0 || Layout) && !
Sym.isWeakExternal()) {
487 Sym.setIsResolving(
true);
490 Asm && Asm->getContext().getAsmInfo()->hasSubsectionsViaSymbols();
491 if (!
Sym.getVariableValue()->evaluateAsRelocatableImpl(Res, Asm,
499 if (InSet || !(
A && !
B &&
A->isInSection())) {
511 Res.Specifier = Kind;
543 if (!
Value.isAbsolute())
557 if (!
Value.isAbsolute())
605 RHSValue.Cst = -(
uint64_t)RHSValue.Cst;
608 LHSValue.Cst += RHSValue.Cst;
613 RHSValue.Cst += LHSValue.Cst;
617 if (LHSValue.SymB && LHSValue.Specifier)
619 if (RHSValue.SymB && RHSValue.Specifier)
685 return Asm && Asm->getContext().getAsmInfo()->evaluateAsRelocatableImpl(
686 cast<MCSpecifierExpr>(*
this), Res, Asm);
696 return cast<MCTargetExpr>(
this)->findAssociatedFragment();
703 const_cast<MCSymbol &
>(cast<MCSymbolRefExpr>(
this)->getSymbol());
706 if (
Sym.isResolving())
708 Sym.setIsResolving(
true);
709 auto *
F =
Sym.getFragment();
710 Sym.setIsResolving(
false);
715 return cast<MCUnaryExpr>(
this)->getSubExpr()->findAssociatedFragment();
733 return LHS_F ? LHS_F : RHS_F;
737 return cast<MCSpecifierExpr>(
this)->getSubExpr()->findAssociatedFragment();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, bool InSet, const MCSymbol *&A, const MCSymbol *&B, int64_t &Addend)
Helper method for.
static int getPrecedence(MCBinaryExpr::Opcode Op)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class represents an Operation in the Expression.
This class is intended to be used as a base class for asm properties and features specific to the tar...
virtual void printSpecifierExpr(raw_ostream &, const MCSpecifierExpr &) const
StringRef getSpecifierName(uint32_t S) const
bool useParensForSpecifier() const
Binary assembler expressions.
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Opcode getOpcode() const
Get the kind of this binary expression.
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
@ AShr
Arithmetic shift right.
@ LShr
Logical shift right.
@ GTE
Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).
@ GT
Signed greater than comparison (result is either 0 or some target-specific non-zero value)
@ Xor
Bitwise exclusive or.
@ LT
Signed less than comparison (result is either 0 or some target-specific non-zero value).
@ LTE
Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).
@ NE
Inequality comparison.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
const MCAsmInfo * getAsmInfo() const
Base class for the full range of assembler expressions which are needed for parsing.
LLVM_ABI bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const
Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables.
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
@ Unary
Unary expressions.
@ Constant
Constant expressions.
@ SymbolRef
References to labels and assigned expressions.
@ Target
Target specific expression.
@ Specifier
Expression with a relocation specifier.
@ Binary
Binary expressions.
static LLVM_ABI bool evaluateSymbolicAdd(const MCAssembler *, bool, const MCValue &, const MCValue &, MCValue &)
LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const
Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.
LLVM_ABI MCFragment * findAssociatedFragment() const
Find the "associated section" for this expression, which is currently defined as the absolute section...
LLVM_ABI bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, bool InSet) const
LLVM_ABI void dump() const
unsigned getLayoutOrder() const
MCSection * getParent() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
bool isLinkerRelaxable() const
Extension point for target-specific MCExpr subclasses with a relocation specifier,...
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isUndefined() const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
bool isVariable() const
isVariable - Check if this is a variable symbol.
static LLVM_ABI MCFragment * AbsolutePseudoFragment
MCFragment * getFragment() const
uint64_t getOffset() const
Extension point for target-specific MCExpr subclasses to implement.
Unary assembler expressions.
Opcode getOpcode() const
Get the kind of this unary expression.
static LLVM_ABI const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
const MCExpr * getSubExpr() const
Get the child of this unary expression.
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
const MCSymbol * getAddSym() const
int64_t getConstant() const
uint32_t getSpecifier() const
const MCSymbol * getSubSym() const
bool isAbsolute() const
Is this an absolute (as opposed to relocatable) value.
Represents a location in source code.
static Twine utohexstr(const uint64_t &Val)
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.