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 << '(';
83 OS << ')';
84 } else
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 ( ||
)
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
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 .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 ( &&
)
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 (.isAbsolute())
920 return false;
922 break;
924
925 if (Value.getSymA() && .getSymB())
926 return false;
927
928
931 break;
933 if (.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.