LLVM: lib/MC/MCExpr.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12#include "llvm/Config/llvm-config.h"

25#include

26#include

27

28using namespace llvm;

29

30#define DEBUG_TYPE "mcexpr"

31

32namespace {

34

35STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");

36

37}

38}

39

43 return cast(this)->printImpl(OS, MAI);

45 auto Value = cast(*this).getValue();

46 auto PrintInHex = cast(*this).useHexFormat();

47 auto SizeInBytes = cast(*this).getSizeInBytes();

48 if (Value < 0 && MAI && !MAI->supportsSignedData())

49 PrintInHex = true;

50 if (PrintInHex)

51 switch (SizeInBytes) {

52 default:

54 break;

55 case 1:

57 break;

58 case 2:

60 break;

61 case 4:

63 break;

64 case 8:

66 break;

67 }

68 else

70 return;

71 }

73 const MCSymbolRefExpr &SRE = cast(*this);

75

76

78 Sym.getName().starts_with('$');

79

80 if (UseParens) {

81 OS << '(';

82 Sym.print(OS, MAI);

83 OS << ')';

84 } else

85 Sym.print(OS, MAI);

86

91 else

93 }

94

95 return;

96 }

97

99 const MCUnaryExpr &UE = cast(*this);

105 }

110 return;

111 }

112

114 const MCBinaryExpr &BE = cast(*this);

115

116

117 if (isa(BE.getLHS()) || isa(BE.getLHS())) {

119 } else {

120 OS << '(';

122 OS << ')';

123 }

124

127

129 if (RHSC->getValue() < 0) {

130 OS << RHSC->getValue();

131 return;

132 }

133 }

134

135 OS << '+';

136 break;

156 }

157

158

159 if (isa(BE.getRHS()) || isa(BE.getRHS())) {

161 } else {

162 OS << '(';

164 OS << ')';

165 }

166 return;

167 }

168 }

169

171}

172

173#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

175 dbgs() << *this;

176 dbgs() << '\n';

177}

178#endif

179

186 }

189 return TE->isSymbolUsedInExpression(Sym);

190 }

192 return false;

197 return &S == Sym;

198 }

200 const MCExpr *SubExpr =

201 static_cast<const MCUnaryExpr *>(this)->getSubExpr();

203 }

204 }

205

207}

208

209

210

215}

216

219 return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);

220}

221

223 bool PrintInHex,

224 unsigned SizeInBytes) {

226}

227

228

229

230MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,

233 encodeSubclassData(Kind, MAI->hasSubsectionsViaSymbols())),

234 Symbol(Symbol) {

236}

237

242}

243

247}

248

250 switch (Kind) {

251

252 case VK_Invalid: return "<>";

253 case VK_None: return "<>";

254

257 case VK_GOT: return "GOT";

261 case VK_PCREL: return "PCREL";

269 case VK_PLT: return "PLT";

270 case VK_TLSGD: return "TLSGD";

272 case VK_TLSLD: return "TLSLD";

275 case VK_TPOFF: return "TPOFF";

276 case VK_TPREL: return "TPREL";

279 case VK_TLVP: return "TLVP";

282 case VK_PAGE: return "PAGE";

286 case VK_SECREL: return "SECREL32";

287 case VK_SIZE: return "SIZE";

363 return "gd";

365 return "m";

367 return "ie";

369 return "le";

371 return "ld";

373 return "ml";

379 return "got@pcrel";

381 return "got@tlsgd@pcrel";

383 return "got@tlsld@pcrel";

385 return "got@tprel@pcrel";

387 return "tls@pcrel";

429

430 }

432}

433

569}

570

571

572

573void MCTargetExpr::anchor() {}

574

575

576

577bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {

578 return evaluateAsAbsolute(Res, nullptr, nullptr, false);

579}

580

581bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm,

583

584

585 return evaluateAsAbsolute(Res, &Asm, &Addrs, true);

586}

587

588bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {

589 return evaluateAsAbsolute(Res, &Asm, nullptr, false);

590}

591

592bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {

593 return evaluateAsAbsolute(Res, Asm, nullptr, false);

594}

595

597 return evaluateAsAbsolute(Res, &Asm, nullptr, true);

598}

599

600bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,

603

604

605 if (const MCConstantExpr *CE = dyn_cast(this)) {

606 Res = CE->getValue();

607 return true;

608 }

609

610 bool IsRelocatable =

612

613

614 Res = Value.getConstant();

615

616 return IsRelocatable && Value.isAbsolute();

617}

618

619

623 if (A || B)

624 return;

625

626 const MCSymbol &SA = A->getSymbol();

627 const MCSymbol &SB = B->getSymbol();

628

630 return;

631

632 if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))

633 return;

634

635 auto FinalizeFolding = [&]() {

636

637

638 if (Asm->isThumbFunc(&SA))

639 Addend |= 1;

640

641

642

643 A = B = nullptr;

644 };

645

650 if ((&SecA != &SecB) && !Addrs)

651 return;

652

653

654

655

656

657

658

659 bool Layout = Asm->hasLayout();

661 !Asm->getBackend().allowLinkerRelaxation())) {

662

663

666 return FinalizeFolding();

667 }

668

669

670 Addend += Asm->getSymbolOffset(A->getSymbol()) -

671 Asm->getSymbolOffset(B->getSymbol());

672 if (Addrs && (&SecA != &SecB))

673 Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));

674

675 FinalizeFolding();

676 } else {

677

678

679

680

681

682

683

685 return;

686

687

688

690 if (FA == FB)

692 else

694

700 Displacement *= -1;

701 }

702

703

704

705

706

707 bool BBeforeRelax = false, AAfterRelax = false;

708 for (auto FI = FB; FI; FI = FI->getNext()) {

709 auto DF = dyn_cast(FI);

710 if (DF && DF->isLinkerRelaxable()) {

711 if (&*FI != FB || SBOffset != DF->getContents().size())

712 BBeforeRelax = true;

713 if (&*FI != FA || SAOffset == DF->getContents().size())

714 AAfterRelax = true;

715 if (BBeforeRelax && AAfterRelax)

716 return;

717 }

718 if (&*FI == FA) {

719

720

721 Addend += Reverse ? -Displacement : Displacement;

722 FinalizeFolding();

723 return;

724 }

725

726 int64_t Num;

727 unsigned Count;

728 if (DF) {

729 Displacement += DF->getContents().size();

730 } else if (auto *AF = dyn_cast(FI);

731 AF && Layout && AF->hasEmitNops() &&

732 !Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign(

733 *AF, Count)) {

734 Displacement += Asm->computeFragmentSize(*AF);

735 } else if (auto *FF = dyn_cast(FI);

736 FF && FF->getNumValues().evaluateAsAbsolute(Num)) {

737 Displacement += Num * FF->getValueSize();

738 } else {

739 return;

740 }

741 }

742 }

743}

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

768

769

772 int64_t LHS_Cst = LHS.getConstant();

773

776 int64_t RHS_Cst = RHS.getConstant();

777

778 if (LHS.getRefKind() != RHS.getRefKind())

779 return false;

780

781

782 int64_t Result_Cst = LHS_Cst + RHS_Cst;

783

784

785 if (Asm) {

786

787

788

789

790

791

792

793

794

795

797 Result_Cst);

799 Result_Cst);

801 Result_Cst);

803 Result_Cst);

804 }

805

806

807 if ((LHS_A && RHS_A) || (LHS_B && RHS_B))

808 return false;

809

810

811

814

816 return true;

817}

818

822}

823

826}

827

829 if (Sym.isWeakExternal())

830 return false;

831

832 const MCExpr *Expr = Sym.getVariableValue();

833 const auto *Inner = dyn_cast(Expr);

834 if (Inner) {

836 return false;

837 }

838

839 if (InSet)

840 return true;

841 return Sym.isInSection();

842}

843

847 bool InSet) const {

848 ++stats::MCExprEvaluate;

851 return cast(this)->evaluateAsRelocatableImpl(Res, Asm, Fixup);

852

854 Res = MCValue::get(cast(this)->getValue());

855 return true;

856

858 const MCSymbolRefExpr *SRE = cast(this);

860 const auto Kind = SRE->getKind();

861 bool Layout = Asm && Asm->hasLayout();

862

863

867 if (Sym.getVariableValue()->evaluateAsRelocatableImpl(

868 Res, Asm, Fixup, Addrs, InSet || IsMachO)) {

872 return true;

873 }

874

875

876

879 return false;

880 Res =

882 Kind, Asm->getContext()),

884 }

885 if (!IsMachO)

886 return true;

887

890

891

892

893

894

895

896

897 if (A && B)

898 return true;

899

901 return true;

902 }

903 }

904

906 return true;

907 }

908

910 const MCUnaryExpr *AUE = cast(this);

912

914 InSet))

915 return false;

916

919 if (Value.isAbsolute())

920 return false;

922 break;

924

925 if (Value.getSymA() && Value.getSymB())

926 return false;

927

928

931 break;

933 if (Value.isAbsolute())

934 return false;

936 break;

939 break;

940 }

941

942 return true;

943 }

944

946 const MCBinaryExpr *ABE = cast(this);

947 MCValue LHSValue, RHSValue;

948

950 InSet) ||

952 InSet)) {

953

958 Res = MCValue::get(L->isEqualTo(R) ? -1 : 0);

959 return true;

961 Res = MCValue::get(L->isEqualTo(R) ? 0 : -1);

962 return true;

963 default:

964 break;

965 }

966 }

967 }

968 return false;

969 }

970

971

972

975 default:

976 return false;

978

979

981 Asm, Addrs, InSet, LHSValue,

985 Res);

986

989 Asm, Addrs, InSet, LHSValue,

992 Res);

993 }

994 }

995

996

997

998

1000 int64_t Result = 0;

1002 switch (Op) {

1008

1009

1010

1011

1012

1013

1014 if (RHS == 0)

1015 return false;

1018 else

1020 break;

1036 }

1037

1038 switch (Op) {

1039 default:

1041 break;

1048

1050 break;

1051 }

1052

1053 return true;

1054 }

1055 }

1056

1058}

1059

1063

1064 return cast(this)->findAssociatedFragment();

1065

1068

1070 const MCSymbolRefExpr *SRE = cast(this);

1072 return Sym.getFragment();

1073 }

1074

1076 return cast(this)->getSubExpr()->findAssociatedFragment();

1077

1079 const MCBinaryExpr *BE = cast(this);

1082

1083

1085 return RHS_F;

1087 return LHS_F;

1088

1089

1092

1093

1094 return LHS_F ? LHS_F : RHS_F;

1095 }

1096 }

1097

1099}

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 RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")

static bool canExpand(const MCSymbol &Sym, bool InSet)

static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, const MCSymbolRefExpr *&B, int64_t &Addend)

Helper method for.

static bool evaluateSymbolicAdd(const MCAssembler *Asm, const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, const MCValue &RHS, MCValue &Res)

Evaluate the result of an add between (conceptually) two MCValues.

PowerPC TLS Dynamic Call Fixup

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...

This class represents an Operation in the Expression.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

This class is intended to be used as a base class for asm properties and features specific to the tar...

bool useParensForSymbolVariant() const

bool useParensForDollarSignNames() 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 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 const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

const MCAsmInfo * getAsmInfo() const

MCSymbol * getOrCreateSymbol(const Twine &Name)

Lookup the symbol inside with the specified Name.

Base class for the full range of assembler expressions which are needed for parsing.

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.

bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet) const

@ Unary

Unary expressions.

@ Constant

Constant expressions.

@ SymbolRef

References to labels and assigned expressions.

@ Target

Target specific expression.

@ Binary

Binary expressions.

bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const

Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.

bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm, const MCFixup *Fixup) const

Try to evaluate the expression to a relocatable value, i.e.

bool isSymbolUsedInExpression(const MCSymbol *Sym) const

Returns whether the given symbol is used anywhere in the expression or subexpressions.

void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const

MCFragment * findAssociatedFragment() const

Find the "associated section" for this expression, which is currently defined as the absolute section...

Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...

unsigned getLayoutOrder() const

MCSection * getParent() const

MCFragment * getNext() const

Instances of this class represent a uniqued identifier for a section in the current translation unit.

bool hasInstructions() const

Represent a reference to a symbol from inside an expression.

const MCSymbol & getSymbol() const

static StringRef getVariantKindName(VariantKind Kind)

static VariantKind getVariantKindForName(StringRef Name)

@ VK_AMDGPU_GOTPCREL32_LO

@ VK_AMDGPU_GOTPCREL32_HI

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)

VariantKind getKind() const

bool hasSubsectionsViaSymbols() const

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

const MCExpr * getVariableValue(bool SetUsed=true) const

getVariableValue - Get the value for variable symbols.

bool isWeakExternal() const

bool isVariable() const

isVariable - Check if this is a variable symbol.

bool isUndefined(bool SetUsed=true) const

isUndefined - Check if this symbol undefined (i.e., implicitly defined).

static MCFragment * AbsolutePseudoFragment

uint64_t getOffset() const

MCFragment * getFragment(bool SetUsed=true) const

This is an extension point for target-specific MCExpr subclasses to implement.

Unary assembler expressions.

Opcode getOpcode() const

Get the kind of this unary expression.

static const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())

const MCExpr * getSubExpr() const

Get the child of this unary expression.

This represents an "assembler immediate".

int64_t getConstant() const

uint32_t getRefKind() const

static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=nullptr, int64_t Val=0, uint32_t RefKind=0)

const MCSymbolRefExpr * getSymB() const

const MCSymbolRefExpr * getSymA() const

bool isAbsolute() const

Is this an absolute (as opposed to relocatable) value.

Represents a location in source code.

StringRef - Represent a constant reference to a string, i.e.

A switch()-like statement whose cases are string literals.

StringSwitch & Case(StringLiteral S, T Value)

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.

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.