10b57cec5SDimitry Andric //===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 100b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 110b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 120b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 130b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCAsmLayout.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 210b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 220b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 230b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 260b57cec5SDimitry Andric #include <cassert> 270b57cec5SDimitry Andric #include <cstdint> 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace llvm; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define DEBUG_TYPE "mcexpr" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace { 340b57cec5SDimitry Andric namespace stats { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric } // end namespace stats 390b57cec5SDimitry Andric } // end anonymous namespace 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { 420b57cec5SDimitry Andric switch (getKind()) { 430b57cec5SDimitry Andric case MCExpr::Target: 440b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->printImpl(OS, MAI); 450b57cec5SDimitry Andric case MCExpr::Constant: { 460b57cec5SDimitry Andric auto Value = cast<MCConstantExpr>(*this).getValue(); 470b57cec5SDimitry Andric auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat(); 485ffd83dbSDimitry Andric auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes(); 49e8d8bef9SDimitry Andric if (Value < 0 && MAI && !MAI->supportsSignedData()) 50e8d8bef9SDimitry Andric PrintInHex = true; 510b57cec5SDimitry Andric if (PrintInHex) 525ffd83dbSDimitry Andric switch (SizeInBytes) { 535ffd83dbSDimitry Andric default: 540b57cec5SDimitry Andric OS << "0x" << Twine::utohexstr(Value); 555ffd83dbSDimitry Andric break; 565ffd83dbSDimitry Andric case 1: 575ffd83dbSDimitry Andric OS << format("0x%02" PRIx64, Value); 585ffd83dbSDimitry Andric break; 595ffd83dbSDimitry Andric case 2: 605ffd83dbSDimitry Andric OS << format("0x%04" PRIx64, Value); 615ffd83dbSDimitry Andric break; 625ffd83dbSDimitry Andric case 4: 635ffd83dbSDimitry Andric OS << format("0x%08" PRIx64, Value); 645ffd83dbSDimitry Andric break; 655ffd83dbSDimitry Andric case 8: 665ffd83dbSDimitry Andric OS << format("0x%016" PRIx64, Value); 675ffd83dbSDimitry Andric break; 685ffd83dbSDimitry Andric } 690b57cec5SDimitry Andric else 700b57cec5SDimitry Andric OS << Value; 710b57cec5SDimitry Andric return; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric case MCExpr::SymbolRef: { 740b57cec5SDimitry Andric const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); 750b57cec5SDimitry Andric const MCSymbol &Sym = SRE.getSymbol(); 760b57cec5SDimitry Andric // Parenthesize names that start with $ so that they don't look like 770b57cec5SDimitry Andric // absolute names. 7881ad6265SDimitry Andric bool UseParens = MAI && MAI->useParensForDollarSignNames() && !InParens && 7981ad6265SDimitry Andric !Sym.getName().empty() && Sym.getName()[0] == '$'; 8081ad6265SDimitry Andric 810b57cec5SDimitry Andric if (UseParens) { 820b57cec5SDimitry Andric OS << '('; 830b57cec5SDimitry Andric Sym.print(OS, MAI); 840b57cec5SDimitry Andric OS << ')'; 850b57cec5SDimitry Andric } else 860b57cec5SDimitry Andric Sym.print(OS, MAI); 870b57cec5SDimitry Andric 88e8d8bef9SDimitry Andric const MCSymbolRefExpr::VariantKind Kind = SRE.getKind(); 89e8d8bef9SDimitry Andric if (Kind != MCSymbolRefExpr::VK_None) { 90e8d8bef9SDimitry Andric if (MAI && MAI->useParensForSymbolVariant()) // ARM 91e8d8bef9SDimitry Andric OS << '(' << MCSymbolRefExpr::getVariantKindName(Kind) << ')'; 92e8d8bef9SDimitry Andric else 93e8d8bef9SDimitry Andric OS << '@' << MCSymbolRefExpr::getVariantKindName(Kind); 94e8d8bef9SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric return; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric case MCExpr::Unary: { 1000b57cec5SDimitry Andric const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 1010b57cec5SDimitry Andric switch (UE.getOpcode()) { 1020b57cec5SDimitry Andric case MCUnaryExpr::LNot: OS << '!'; break; 1030b57cec5SDimitry Andric case MCUnaryExpr::Minus: OS << '-'; break; 1040b57cec5SDimitry Andric case MCUnaryExpr::Not: OS << '~'; break; 1050b57cec5SDimitry Andric case MCUnaryExpr::Plus: OS << '+'; break; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary; 1080b57cec5SDimitry Andric if (Binary) OS << "("; 1090b57cec5SDimitry Andric UE.getSubExpr()->print(OS, MAI); 1100b57cec5SDimitry Andric if (Binary) OS << ")"; 1110b57cec5SDimitry Andric return; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric case MCExpr::Binary: { 1150b57cec5SDimitry Andric const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // Only print parens around the LHS if it is non-trivial. 1180b57cec5SDimitry Andric if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 1190b57cec5SDimitry Andric BE.getLHS()->print(OS, MAI); 1200b57cec5SDimitry Andric } else { 1210b57cec5SDimitry Andric OS << '('; 1220b57cec5SDimitry Andric BE.getLHS()->print(OS, MAI); 1230b57cec5SDimitry Andric OS << ')'; 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric switch (BE.getOpcode()) { 1270b57cec5SDimitry Andric case MCBinaryExpr::Add: 1280b57cec5SDimitry Andric // Print "X-42" instead of "X+-42". 1290b57cec5SDimitry Andric if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 1300b57cec5SDimitry Andric if (RHSC->getValue() < 0) { 1310b57cec5SDimitry Andric OS << RHSC->getValue(); 1320b57cec5SDimitry Andric return; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric OS << '+'; 1370b57cec5SDimitry Andric break; 1380b57cec5SDimitry Andric case MCBinaryExpr::AShr: OS << ">>"; break; 1390b57cec5SDimitry Andric case MCBinaryExpr::And: OS << '&'; break; 1400b57cec5SDimitry Andric case MCBinaryExpr::Div: OS << '/'; break; 1410b57cec5SDimitry Andric case MCBinaryExpr::EQ: OS << "=="; break; 1420b57cec5SDimitry Andric case MCBinaryExpr::GT: OS << '>'; break; 1430b57cec5SDimitry Andric case MCBinaryExpr::GTE: OS << ">="; break; 1440b57cec5SDimitry Andric case MCBinaryExpr::LAnd: OS << "&&"; break; 1450b57cec5SDimitry Andric case MCBinaryExpr::LOr: OS << "||"; break; 1460b57cec5SDimitry Andric case MCBinaryExpr::LShr: OS << ">>"; break; 1470b57cec5SDimitry Andric case MCBinaryExpr::LT: OS << '<'; break; 1480b57cec5SDimitry Andric case MCBinaryExpr::LTE: OS << "<="; break; 1490b57cec5SDimitry Andric case MCBinaryExpr::Mod: OS << '%'; break; 1500b57cec5SDimitry Andric case MCBinaryExpr::Mul: OS << '*'; break; 1510b57cec5SDimitry Andric case MCBinaryExpr::NE: OS << "!="; break; 1520b57cec5SDimitry Andric case MCBinaryExpr::Or: OS << '|'; break; 153e8d8bef9SDimitry Andric case MCBinaryExpr::OrNot: OS << '!'; break; 1540b57cec5SDimitry Andric case MCBinaryExpr::Shl: OS << "<<"; break; 1550b57cec5SDimitry Andric case MCBinaryExpr::Sub: OS << '-'; break; 1560b57cec5SDimitry Andric case MCBinaryExpr::Xor: OS << '^'; break; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric // Only print parens around the LHS if it is non-trivial. 1600b57cec5SDimitry Andric if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 1610b57cec5SDimitry Andric BE.getRHS()->print(OS, MAI); 1620b57cec5SDimitry Andric } else { 1630b57cec5SDimitry Andric OS << '('; 1640b57cec5SDimitry Andric BE.getRHS()->print(OS, MAI); 1650b57cec5SDimitry Andric OS << ')'; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric return; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric llvm_unreachable("Invalid expression kind!"); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1750b57cec5SDimitry Andric LLVM_DUMP_METHOD void MCExpr::dump() const { 1760b57cec5SDimitry Andric dbgs() << *this; 1770b57cec5SDimitry Andric dbgs() << '\n'; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric #endif 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric /* *** */ 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, 1840b57cec5SDimitry Andric const MCExpr *RHS, MCContext &Ctx, 1850b57cec5SDimitry Andric SMLoc Loc) { 1860b57cec5SDimitry Andric return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, 1900b57cec5SDimitry Andric MCContext &Ctx, SMLoc Loc) { 1910b57cec5SDimitry Andric return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, 1955ffd83dbSDimitry Andric bool PrintInHex, 1965ffd83dbSDimitry Andric unsigned SizeInBytes) { 1975ffd83dbSDimitry Andric return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric /* *** */ 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, 2030b57cec5SDimitry Andric const MCAsmInfo *MAI, SMLoc Loc) 2045ffd83dbSDimitry Andric : MCExpr(MCExpr::SymbolRef, Loc, 205e8d8bef9SDimitry Andric encodeSubclassData(Kind, MAI->hasSubsectionsViaSymbols())), 2060b57cec5SDimitry Andric Symbol(Symbol) { 2070b57cec5SDimitry Andric assert(Symbol); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, 2110b57cec5SDimitry Andric VariantKind Kind, 2120b57cec5SDimitry Andric MCContext &Ctx, SMLoc Loc) { 2130b57cec5SDimitry Andric return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, 2170b57cec5SDimitry Andric MCContext &Ctx) { 2180b57cec5SDimitry Andric return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 2220b57cec5SDimitry Andric switch (Kind) { 2230b57cec5SDimitry Andric case VK_Invalid: return "<<invalid>>"; 2240b57cec5SDimitry Andric case VK_None: return "<<none>>"; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric case VK_DTPOFF: return "DTPOFF"; 2270b57cec5SDimitry Andric case VK_DTPREL: return "DTPREL"; 2280b57cec5SDimitry Andric case VK_GOT: return "GOT"; 2290b57cec5SDimitry Andric case VK_GOTOFF: return "GOTOFF"; 2300b57cec5SDimitry Andric case VK_GOTREL: return "GOTREL"; 2315ffd83dbSDimitry Andric case VK_PCREL: return "PCREL"; 2320b57cec5SDimitry Andric case VK_GOTPCREL: return "GOTPCREL"; 233349cc55cSDimitry Andric case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX"; 2340b57cec5SDimitry Andric case VK_GOTTPOFF: return "GOTTPOFF"; 2350b57cec5SDimitry Andric case VK_INDNTPOFF: return "INDNTPOFF"; 2360b57cec5SDimitry Andric case VK_NTPOFF: return "NTPOFF"; 2370b57cec5SDimitry Andric case VK_GOTNTPOFF: return "GOTNTPOFF"; 2380b57cec5SDimitry Andric case VK_PLT: return "PLT"; 2390b57cec5SDimitry Andric case VK_TLSGD: return "TLSGD"; 2400b57cec5SDimitry Andric case VK_TLSLD: return "TLSLD"; 2410b57cec5SDimitry Andric case VK_TLSLDM: return "TLSLDM"; 2420b57cec5SDimitry Andric case VK_TPOFF: return "TPOFF"; 2430b57cec5SDimitry Andric case VK_TPREL: return "TPREL"; 2440b57cec5SDimitry Andric case VK_TLSCALL: return "tlscall"; 2450b57cec5SDimitry Andric case VK_TLSDESC: return "tlsdesc"; 2460b57cec5SDimitry Andric case VK_TLVP: return "TLVP"; 2470b57cec5SDimitry Andric case VK_TLVPPAGE: return "TLVPPAGE"; 2480b57cec5SDimitry Andric case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; 2490b57cec5SDimitry Andric case VK_PAGE: return "PAGE"; 2500b57cec5SDimitry Andric case VK_PAGEOFF: return "PAGEOFF"; 2510b57cec5SDimitry Andric case VK_GOTPAGE: return "GOTPAGE"; 2520b57cec5SDimitry Andric case VK_GOTPAGEOFF: return "GOTPAGEOFF"; 2530b57cec5SDimitry Andric case VK_SECREL: return "SECREL32"; 2540b57cec5SDimitry Andric case VK_SIZE: return "SIZE"; 2550b57cec5SDimitry Andric case VK_WEAKREF: return "WEAKREF"; 2560b57cec5SDimitry Andric case VK_X86_ABS8: return "ABS8"; 257e8d8bef9SDimitry Andric case VK_X86_PLTOFF: return "PLTOFF"; 2580b57cec5SDimitry Andric case VK_ARM_NONE: return "none"; 2590b57cec5SDimitry Andric case VK_ARM_GOT_PREL: return "GOT_PREL"; 2600b57cec5SDimitry Andric case VK_ARM_TARGET1: return "target1"; 2610b57cec5SDimitry Andric case VK_ARM_TARGET2: return "target2"; 2620b57cec5SDimitry Andric case VK_ARM_PREL31: return "prel31"; 2630b57cec5SDimitry Andric case VK_ARM_SBREL: return "sbrel"; 2640b57cec5SDimitry Andric case VK_ARM_TLSLDO: return "tlsldo"; 2650b57cec5SDimitry Andric case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; 2660b57cec5SDimitry Andric case VK_AVR_NONE: return "none"; 2670b57cec5SDimitry Andric case VK_AVR_LO8: return "lo8"; 2680b57cec5SDimitry Andric case VK_AVR_HI8: return "hi8"; 2690b57cec5SDimitry Andric case VK_AVR_HLO8: return "hlo8"; 2700b57cec5SDimitry Andric case VK_AVR_DIFF8: return "diff8"; 2710b57cec5SDimitry Andric case VK_AVR_DIFF16: return "diff16"; 2720b57cec5SDimitry Andric case VK_AVR_DIFF32: return "diff32"; 273fe6060f1SDimitry Andric case VK_AVR_PM: return "pm"; 2740b57cec5SDimitry Andric case VK_PPC_LO: return "l"; 2750b57cec5SDimitry Andric case VK_PPC_HI: return "h"; 2760b57cec5SDimitry Andric case VK_PPC_HA: return "ha"; 2770b57cec5SDimitry Andric case VK_PPC_HIGH: return "high"; 2780b57cec5SDimitry Andric case VK_PPC_HIGHA: return "higha"; 2790b57cec5SDimitry Andric case VK_PPC_HIGHER: return "higher"; 2800b57cec5SDimitry Andric case VK_PPC_HIGHERA: return "highera"; 2810b57cec5SDimitry Andric case VK_PPC_HIGHEST: return "highest"; 2820b57cec5SDimitry Andric case VK_PPC_HIGHESTA: return "highesta"; 2830b57cec5SDimitry Andric case VK_PPC_GOT_LO: return "got@l"; 2840b57cec5SDimitry Andric case VK_PPC_GOT_HI: return "got@h"; 2850b57cec5SDimitry Andric case VK_PPC_GOT_HA: return "got@ha"; 2860b57cec5SDimitry Andric case VK_PPC_TOCBASE: return "tocbase"; 2870b57cec5SDimitry Andric case VK_PPC_TOC: return "toc"; 2880b57cec5SDimitry Andric case VK_PPC_TOC_LO: return "toc@l"; 2890b57cec5SDimitry Andric case VK_PPC_TOC_HI: return "toc@h"; 2900b57cec5SDimitry Andric case VK_PPC_TOC_HA: return "toc@ha"; 2918bcb0991SDimitry Andric case VK_PPC_U: return "u"; 2928bcb0991SDimitry Andric case VK_PPC_L: return "l"; 2930b57cec5SDimitry Andric case VK_PPC_DTPMOD: return "dtpmod"; 2940b57cec5SDimitry Andric case VK_PPC_TPREL_LO: return "tprel@l"; 2950b57cec5SDimitry Andric case VK_PPC_TPREL_HI: return "tprel@h"; 2960b57cec5SDimitry Andric case VK_PPC_TPREL_HA: return "tprel@ha"; 2970b57cec5SDimitry Andric case VK_PPC_TPREL_HIGH: return "tprel@high"; 2980b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHA: return "tprel@higha"; 2990b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHER: return "tprel@higher"; 3000b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; 3010b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; 3020b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; 3030b57cec5SDimitry Andric case VK_PPC_DTPREL_LO: return "dtprel@l"; 3040b57cec5SDimitry Andric case VK_PPC_DTPREL_HI: return "dtprel@h"; 3050b57cec5SDimitry Andric case VK_PPC_DTPREL_HA: return "dtprel@ha"; 3060b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGH: return "dtprel@high"; 3070b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHA: return "dtprel@higha"; 3080b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; 3090b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; 3100b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; 3110b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; 3120b57cec5SDimitry Andric case VK_PPC_GOT_TPREL: return "got@tprel"; 3130b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; 3140b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; 3150b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; 3160b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL: return "got@dtprel"; 3170b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; 3180b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; 3190b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; 3200b57cec5SDimitry Andric case VK_PPC_TLS: return "tls"; 3210b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD: return "got@tlsgd"; 3220b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; 3230b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; 3240b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; 3250b57cec5SDimitry Andric case VK_PPC_TLSGD: return "tlsgd"; 326fe6060f1SDimitry Andric case VK_PPC_AIX_TLSGD: 327fe6060f1SDimitry Andric return "gd"; 328fe6060f1SDimitry Andric case VK_PPC_AIX_TLSGDM: 329fe6060f1SDimitry Andric return "m"; 330*06c3fb27SDimitry Andric case VK_PPC_AIX_TLSLE: 331*06c3fb27SDimitry Andric return "le"; 3320b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD: return "got@tlsld"; 3330b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 3340b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; 3350b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 3365ffd83dbSDimitry Andric case VK_PPC_GOT_PCREL: 3375ffd83dbSDimitry Andric return "got@pcrel"; 338e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSGD_PCREL: 339e8d8bef9SDimitry Andric return "got@tlsgd@pcrel"; 340e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSLD_PCREL: 341e8d8bef9SDimitry Andric return "got@tlsld@pcrel"; 342e8d8bef9SDimitry Andric case VK_PPC_GOT_TPREL_PCREL: 343e8d8bef9SDimitry Andric return "got@tprel@pcrel"; 344e8d8bef9SDimitry Andric case VK_PPC_TLS_PCREL: 345e8d8bef9SDimitry Andric return "tls@pcrel"; 3460b57cec5SDimitry Andric case VK_PPC_TLSLD: return "tlsld"; 3470b57cec5SDimitry Andric case VK_PPC_LOCAL: return "local"; 3485ffd83dbSDimitry Andric case VK_PPC_NOTOC: return "notoc"; 349e8d8bef9SDimitry Andric case VK_PPC_PCREL_OPT: return "<<invalid>>"; 3500b57cec5SDimitry Andric case VK_COFF_IMGREL32: return "IMGREL"; 3510b57cec5SDimitry Andric case VK_Hexagon_LO16: return "LO16"; 3520b57cec5SDimitry Andric case VK_Hexagon_HI16: return "HI16"; 3530b57cec5SDimitry Andric case VK_Hexagon_GPREL: return "GPREL"; 3540b57cec5SDimitry Andric case VK_Hexagon_GD_GOT: return "GDGOT"; 3550b57cec5SDimitry Andric case VK_Hexagon_LD_GOT: return "LDGOT"; 3560b57cec5SDimitry Andric case VK_Hexagon_GD_PLT: return "GDPLT"; 3570b57cec5SDimitry Andric case VK_Hexagon_LD_PLT: return "LDPLT"; 3580b57cec5SDimitry Andric case VK_Hexagon_IE: return "IE"; 3590b57cec5SDimitry Andric case VK_Hexagon_IE_GOT: return "IEGOT"; 3600b57cec5SDimitry Andric case VK_WASM_TYPEINDEX: return "TYPEINDEX"; 3610b57cec5SDimitry Andric case VK_WASM_MBREL: return "MBREL"; 362e8d8bef9SDimitry Andric case VK_WASM_TLSREL: return "TLSREL"; 3630b57cec5SDimitry Andric case VK_WASM_TBREL: return "TBREL"; 364349cc55cSDimitry Andric case VK_WASM_GOT_TLS: return "GOT@TLS"; 365*06c3fb27SDimitry Andric case VK_WASM_FUNCINDEX: return "FUNCINDEX"; 3660b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; 3670b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; 3680b57cec5SDimitry Andric case VK_AMDGPU_REL32_LO: return "rel32@lo"; 3690b57cec5SDimitry Andric case VK_AMDGPU_REL32_HI: return "rel32@hi"; 3700b57cec5SDimitry Andric case VK_AMDGPU_REL64: return "rel64"; 3710b57cec5SDimitry Andric case VK_AMDGPU_ABS32_LO: return "abs32@lo"; 3720b57cec5SDimitry Andric case VK_AMDGPU_ABS32_HI: return "abs32@hi"; 3735ffd83dbSDimitry Andric case VK_VE_HI32: return "hi"; 3745ffd83dbSDimitry Andric case VK_VE_LO32: return "lo"; 3755ffd83dbSDimitry Andric case VK_VE_PC_HI32: return "pc_hi"; 3765ffd83dbSDimitry Andric case VK_VE_PC_LO32: return "pc_lo"; 3775ffd83dbSDimitry Andric case VK_VE_GOT_HI32: return "got_hi"; 3785ffd83dbSDimitry Andric case VK_VE_GOT_LO32: return "got_lo"; 3795ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: return "gotoff_hi"; 3805ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: return "gotoff_lo"; 3815ffd83dbSDimitry Andric case VK_VE_PLT_HI32: return "plt_hi"; 3825ffd83dbSDimitry Andric case VK_VE_PLT_LO32: return "plt_lo"; 3835ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: return "tls_gd_hi"; 3845ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: return "tls_gd_lo"; 3855ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: return "tpoff_hi"; 3865ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: return "tpoff_lo"; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric llvm_unreachable("Invalid variant kind"); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind 3920b57cec5SDimitry Andric MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 3930b57cec5SDimitry Andric return StringSwitch<VariantKind>(Name.lower()) 3940b57cec5SDimitry Andric .Case("dtprel", VK_DTPREL) 3950b57cec5SDimitry Andric .Case("dtpoff", VK_DTPOFF) 3960b57cec5SDimitry Andric .Case("got", VK_GOT) 3970b57cec5SDimitry Andric .Case("gotoff", VK_GOTOFF) 3980b57cec5SDimitry Andric .Case("gotrel", VK_GOTREL) 3995ffd83dbSDimitry Andric .Case("pcrel", VK_PCREL) 4000b57cec5SDimitry Andric .Case("gotpcrel", VK_GOTPCREL) 401349cc55cSDimitry Andric .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX) 4020b57cec5SDimitry Andric .Case("gottpoff", VK_GOTTPOFF) 4030b57cec5SDimitry Andric .Case("indntpoff", VK_INDNTPOFF) 4040b57cec5SDimitry Andric .Case("ntpoff", VK_NTPOFF) 4050b57cec5SDimitry Andric .Case("gotntpoff", VK_GOTNTPOFF) 4060b57cec5SDimitry Andric .Case("plt", VK_PLT) 4070b57cec5SDimitry Andric .Case("tlscall", VK_TLSCALL) 4080b57cec5SDimitry Andric .Case("tlsdesc", VK_TLSDESC) 4090b57cec5SDimitry Andric .Case("tlsgd", VK_TLSGD) 4100b57cec5SDimitry Andric .Case("tlsld", VK_TLSLD) 4110b57cec5SDimitry Andric .Case("tlsldm", VK_TLSLDM) 4120b57cec5SDimitry Andric .Case("tpoff", VK_TPOFF) 4130b57cec5SDimitry Andric .Case("tprel", VK_TPREL) 4140b57cec5SDimitry Andric .Case("tlvp", VK_TLVP) 4150b57cec5SDimitry Andric .Case("tlvppage", VK_TLVPPAGE) 4160b57cec5SDimitry Andric .Case("tlvppageoff", VK_TLVPPAGEOFF) 4170b57cec5SDimitry Andric .Case("page", VK_PAGE) 4180b57cec5SDimitry Andric .Case("pageoff", VK_PAGEOFF) 4190b57cec5SDimitry Andric .Case("gotpage", VK_GOTPAGE) 4200b57cec5SDimitry Andric .Case("gotpageoff", VK_GOTPAGEOFF) 4210b57cec5SDimitry Andric .Case("imgrel", VK_COFF_IMGREL32) 4220b57cec5SDimitry Andric .Case("secrel32", VK_SECREL) 4230b57cec5SDimitry Andric .Case("size", VK_SIZE) 4240b57cec5SDimitry Andric .Case("abs8", VK_X86_ABS8) 425e8d8bef9SDimitry Andric .Case("pltoff", VK_X86_PLTOFF) 4260b57cec5SDimitry Andric .Case("l", VK_PPC_LO) 4270b57cec5SDimitry Andric .Case("h", VK_PPC_HI) 4280b57cec5SDimitry Andric .Case("ha", VK_PPC_HA) 4290b57cec5SDimitry Andric .Case("high", VK_PPC_HIGH) 4300b57cec5SDimitry Andric .Case("higha", VK_PPC_HIGHA) 4310b57cec5SDimitry Andric .Case("higher", VK_PPC_HIGHER) 4320b57cec5SDimitry Andric .Case("highera", VK_PPC_HIGHERA) 4330b57cec5SDimitry Andric .Case("highest", VK_PPC_HIGHEST) 4340b57cec5SDimitry Andric .Case("highesta", VK_PPC_HIGHESTA) 4350b57cec5SDimitry Andric .Case("got@l", VK_PPC_GOT_LO) 4360b57cec5SDimitry Andric .Case("got@h", VK_PPC_GOT_HI) 4370b57cec5SDimitry Andric .Case("got@ha", VK_PPC_GOT_HA) 4380b57cec5SDimitry Andric .Case("local", VK_PPC_LOCAL) 4390b57cec5SDimitry Andric .Case("tocbase", VK_PPC_TOCBASE) 4400b57cec5SDimitry Andric .Case("toc", VK_PPC_TOC) 4410b57cec5SDimitry Andric .Case("toc@l", VK_PPC_TOC_LO) 4420b57cec5SDimitry Andric .Case("toc@h", VK_PPC_TOC_HI) 4430b57cec5SDimitry Andric .Case("toc@ha", VK_PPC_TOC_HA) 4448bcb0991SDimitry Andric .Case("u", VK_PPC_U) 4458bcb0991SDimitry Andric .Case("l", VK_PPC_L) 4460b57cec5SDimitry Andric .Case("tls", VK_PPC_TLS) 4470b57cec5SDimitry Andric .Case("dtpmod", VK_PPC_DTPMOD) 4480b57cec5SDimitry Andric .Case("tprel@l", VK_PPC_TPREL_LO) 4490b57cec5SDimitry Andric .Case("tprel@h", VK_PPC_TPREL_HI) 4500b57cec5SDimitry Andric .Case("tprel@ha", VK_PPC_TPREL_HA) 4510b57cec5SDimitry Andric .Case("tprel@high", VK_PPC_TPREL_HIGH) 4520b57cec5SDimitry Andric .Case("tprel@higha", VK_PPC_TPREL_HIGHA) 4530b57cec5SDimitry Andric .Case("tprel@higher", VK_PPC_TPREL_HIGHER) 4540b57cec5SDimitry Andric .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) 4550b57cec5SDimitry Andric .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) 4560b57cec5SDimitry Andric .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) 4570b57cec5SDimitry Andric .Case("dtprel@l", VK_PPC_DTPREL_LO) 4580b57cec5SDimitry Andric .Case("dtprel@h", VK_PPC_DTPREL_HI) 4590b57cec5SDimitry Andric .Case("dtprel@ha", VK_PPC_DTPREL_HA) 4600b57cec5SDimitry Andric .Case("dtprel@high", VK_PPC_DTPREL_HIGH) 4610b57cec5SDimitry Andric .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) 4620b57cec5SDimitry Andric .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) 4630b57cec5SDimitry Andric .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) 4640b57cec5SDimitry Andric .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) 4650b57cec5SDimitry Andric .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) 4660b57cec5SDimitry Andric .Case("got@tprel", VK_PPC_GOT_TPREL) 4670b57cec5SDimitry Andric .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 4680b57cec5SDimitry Andric .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) 4690b57cec5SDimitry Andric .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 4700b57cec5SDimitry Andric .Case("got@dtprel", VK_PPC_GOT_DTPREL) 4710b57cec5SDimitry Andric .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) 4720b57cec5SDimitry Andric .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) 4730b57cec5SDimitry Andric .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) 4740b57cec5SDimitry Andric .Case("got@tlsgd", VK_PPC_GOT_TLSGD) 4750b57cec5SDimitry Andric .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 4760b57cec5SDimitry Andric .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) 4770b57cec5SDimitry Andric .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 4780b57cec5SDimitry Andric .Case("got@tlsld", VK_PPC_GOT_TLSLD) 4790b57cec5SDimitry Andric .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 4800b57cec5SDimitry Andric .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) 4810b57cec5SDimitry Andric .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 4825ffd83dbSDimitry Andric .Case("got@pcrel", VK_PPC_GOT_PCREL) 483e8d8bef9SDimitry Andric .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) 484e8d8bef9SDimitry Andric .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) 485e8d8bef9SDimitry Andric .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) 486e8d8bef9SDimitry Andric .Case("tls@pcrel", VK_PPC_TLS_PCREL) 4875ffd83dbSDimitry Andric .Case("notoc", VK_PPC_NOTOC) 4880b57cec5SDimitry Andric .Case("gdgot", VK_Hexagon_GD_GOT) 4890b57cec5SDimitry Andric .Case("gdplt", VK_Hexagon_GD_PLT) 4900b57cec5SDimitry Andric .Case("iegot", VK_Hexagon_IE_GOT) 4910b57cec5SDimitry Andric .Case("ie", VK_Hexagon_IE) 4920b57cec5SDimitry Andric .Case("ldgot", VK_Hexagon_LD_GOT) 4930b57cec5SDimitry Andric .Case("ldplt", VK_Hexagon_LD_PLT) 4940b57cec5SDimitry Andric .Case("none", VK_ARM_NONE) 4950b57cec5SDimitry Andric .Case("got_prel", VK_ARM_GOT_PREL) 4960b57cec5SDimitry Andric .Case("target1", VK_ARM_TARGET1) 4970b57cec5SDimitry Andric .Case("target2", VK_ARM_TARGET2) 4980b57cec5SDimitry Andric .Case("prel31", VK_ARM_PREL31) 4990b57cec5SDimitry Andric .Case("sbrel", VK_ARM_SBREL) 5000b57cec5SDimitry Andric .Case("tlsldo", VK_ARM_TLSLDO) 5010b57cec5SDimitry Andric .Case("lo8", VK_AVR_LO8) 5020b57cec5SDimitry Andric .Case("hi8", VK_AVR_HI8) 5030b57cec5SDimitry Andric .Case("hlo8", VK_AVR_HLO8) 5040b57cec5SDimitry Andric .Case("typeindex", VK_WASM_TYPEINDEX) 5050b57cec5SDimitry Andric .Case("tbrel", VK_WASM_TBREL) 5060b57cec5SDimitry Andric .Case("mbrel", VK_WASM_MBREL) 507e8d8bef9SDimitry Andric .Case("tlsrel", VK_WASM_TLSREL) 508349cc55cSDimitry Andric .Case("got@tls", VK_WASM_GOT_TLS) 509*06c3fb27SDimitry Andric .Case("funcindex", VK_WASM_FUNCINDEX) 5100b57cec5SDimitry Andric .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) 5110b57cec5SDimitry Andric .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) 5120b57cec5SDimitry Andric .Case("rel32@lo", VK_AMDGPU_REL32_LO) 5130b57cec5SDimitry Andric .Case("rel32@hi", VK_AMDGPU_REL32_HI) 5140b57cec5SDimitry Andric .Case("rel64", VK_AMDGPU_REL64) 5150b57cec5SDimitry Andric .Case("abs32@lo", VK_AMDGPU_ABS32_LO) 5160b57cec5SDimitry Andric .Case("abs32@hi", VK_AMDGPU_ABS32_HI) 5175ffd83dbSDimitry Andric .Case("hi", VK_VE_HI32) 5185ffd83dbSDimitry Andric .Case("lo", VK_VE_LO32) 5195ffd83dbSDimitry Andric .Case("pc_hi", VK_VE_PC_HI32) 5205ffd83dbSDimitry Andric .Case("pc_lo", VK_VE_PC_LO32) 5215ffd83dbSDimitry Andric .Case("got_hi", VK_VE_GOT_HI32) 5225ffd83dbSDimitry Andric .Case("got_lo", VK_VE_GOT_LO32) 5235ffd83dbSDimitry Andric .Case("gotoff_hi", VK_VE_GOTOFF_HI32) 5245ffd83dbSDimitry Andric .Case("gotoff_lo", VK_VE_GOTOFF_LO32) 5255ffd83dbSDimitry Andric .Case("plt_hi", VK_VE_PLT_HI32) 5265ffd83dbSDimitry Andric .Case("plt_lo", VK_VE_PLT_LO32) 5275ffd83dbSDimitry Andric .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) 5285ffd83dbSDimitry Andric .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) 5295ffd83dbSDimitry Andric .Case("tpoff_hi", VK_VE_TPOFF_HI32) 5305ffd83dbSDimitry Andric .Case("tpoff_lo", VK_VE_TPOFF_LO32) 5310b57cec5SDimitry Andric .Default(VK_Invalid); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric /* *** */ 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric void MCTargetExpr::anchor() {} 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric /* *** */ 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { 5418bcb0991SDimitry Andric return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5450b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5468bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5500b57cec5SDimitry Andric const MCAsmLayout &Layout, 5510b57cec5SDimitry Andric const SectionAddrMap &Addrs) const { 5528bcb0991SDimitry Andric // Setting InSet causes us to absolutize differences across sections and that 5538bcb0991SDimitry Andric // is what the MachO writer uses Addrs for. 5548bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 5588bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { 5628bcb0991SDimitry Andric return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false); 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric bool MCExpr::evaluateKnownAbsolute(int64_t &Res, 5660b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5670b57cec5SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, 5680b57cec5SDimitry Andric true); 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 5720b57cec5SDimitry Andric const MCAsmLayout *Layout, 5730b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet) const { 5740b57cec5SDimitry Andric MCValue Value; 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Fast path constants. 5770b57cec5SDimitry Andric if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 5780b57cec5SDimitry Andric Res = CE->getValue(); 5790b57cec5SDimitry Andric return true; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric bool IsRelocatable = 5830b57cec5SDimitry Andric evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric // Record the current value. 5860b57cec5SDimitry Andric Res = Value.getConstant(); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric return IsRelocatable && Value.isAbsolute(); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric /// Helper method for \see EvaluateSymbolAdd(). 5920b57cec5SDimitry Andric static void AttemptToFoldSymbolOffsetDifference( 5930b57cec5SDimitry Andric const MCAssembler *Asm, const MCAsmLayout *Layout, 5940b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, 5950b57cec5SDimitry Andric const MCSymbolRefExpr *&B, int64_t &Addend) { 5960b57cec5SDimitry Andric if (!A || !B) 5970b57cec5SDimitry Andric return; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric const MCSymbol &SA = A->getSymbol(); 6000b57cec5SDimitry Andric const MCSymbol &SB = B->getSymbol(); 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric if (SA.isUndefined() || SB.isUndefined()) 6030b57cec5SDimitry Andric return; 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 6060b57cec5SDimitry Andric return; 6070b57cec5SDimitry Andric 608e8d8bef9SDimitry Andric auto FinalizeFolding = [&]() { 6090b57cec5SDimitry Andric // Pointers to Thumb symbols need to have their low-bit set to allow 6100b57cec5SDimitry Andric // for interworking. 6110b57cec5SDimitry Andric if (Asm->isThumbFunc(&SA)) 6120b57cec5SDimitry Andric Addend |= 1; 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric // If symbol is labeled as micromips, we set low-bit to ensure 6150b57cec5SDimitry Andric // correct offset in .gcc_except_table 6160b57cec5SDimitry Andric if (Asm->getBackend().isMicroMips(&SA)) 6170b57cec5SDimitry Andric Addend |= 1; 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric // Clear the symbol expr pointers to indicate we have folded these 6200b57cec5SDimitry Andric // operands. 6210b57cec5SDimitry Andric A = B = nullptr; 622e8d8bef9SDimitry Andric }; 6230b57cec5SDimitry Andric 624e8d8bef9SDimitry Andric const MCFragment *FA = SA.getFragment(); 625e8d8bef9SDimitry Andric const MCFragment *FB = SB.getFragment(); 6265ffd83dbSDimitry Andric const MCSection &SecA = *FA->getParent(); 6275ffd83dbSDimitry Andric const MCSection &SecB = *FB->getParent(); 6280b57cec5SDimitry Andric if ((&SecA != &SecB) && !Addrs) 6290b57cec5SDimitry Andric return; 6300b57cec5SDimitry Andric 631*06c3fb27SDimitry Andric // When layout is available, we can generally compute the difference using the 632*06c3fb27SDimitry Andric // getSymbolOffset path, which also avoids the possible slow fragment walk. 633*06c3fb27SDimitry Andric // However, linker relaxation may cause incorrect fold of A-B if A and B are 634*06c3fb27SDimitry Andric // separated by a linker-relaxable instruction. If the section contains 635*06c3fb27SDimitry Andric // instructions and InSet is false (not expressions in directive like 636*06c3fb27SDimitry Andric // .size/.fill), disable the fast path. 637*06c3fb27SDimitry Andric if (Layout && (InSet || !SecA.hasInstructions() || 638*06c3fb27SDimitry Andric !Asm->getContext().getTargetTriple().isRISCV())) { 639*06c3fb27SDimitry Andric // If both symbols are in the same fragment, return the difference of their 640*06c3fb27SDimitry Andric // offsets. canGetFragmentOffset(FA) may be false. 641*06c3fb27SDimitry Andric if (FA == FB && !SA.isVariable() && !SB.isVariable()) { 642*06c3fb27SDimitry Andric Addend += SA.getOffset() - SB.getOffset(); 643*06c3fb27SDimitry Andric return FinalizeFolding(); 644*06c3fb27SDimitry Andric } 6455ffd83dbSDimitry Andric // One of the symbol involved is part of a fragment being laid out. Quit now 6465ffd83dbSDimitry Andric // to avoid a self loop. 6475ffd83dbSDimitry Andric if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB)) 6485ffd83dbSDimitry Andric return; 6495ffd83dbSDimitry Andric 650e8d8bef9SDimitry Andric // Eagerly evaluate when layout is finalized. 6510b57cec5SDimitry Andric Addend += Layout->getSymbolOffset(A->getSymbol()) - 6520b57cec5SDimitry Andric Layout->getSymbolOffset(B->getSymbol()); 6530b57cec5SDimitry Andric if (Addrs && (&SecA != &SecB)) 6540b57cec5SDimitry Andric Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 6550b57cec5SDimitry Andric 656e8d8bef9SDimitry Andric FinalizeFolding(); 657e8d8bef9SDimitry Andric } else { 658e8d8bef9SDimitry Andric // When layout is not finalized, our ability to resolve differences between 659e8d8bef9SDimitry Andric // symbols is limited to specific cases where the fragments between two 660e8d8bef9SDimitry Andric // symbols (including the fragments the symbols are defined in) are 661e8d8bef9SDimitry Andric // fixed-size fragments so the difference can be calculated. For example, 662e8d8bef9SDimitry Andric // this is important when the Subtarget is changed and a new MCDataFragment 663e8d8bef9SDimitry Andric // is created in the case of foo: instr; .arch_extension ext; instr .if . - 664e8d8bef9SDimitry Andric // foo. 665*06c3fb27SDimitry Andric if (SA.isVariable() || SB.isVariable() || 666e8d8bef9SDimitry Andric FA->getSubsectionNumber() != FB->getSubsectionNumber()) 667e8d8bef9SDimitry Andric return; 668*06c3fb27SDimitry Andric 669e8d8bef9SDimitry Andric // Try to find a constant displacement from FA to FB, add the displacement 670e8d8bef9SDimitry Andric // between the offset in FA of SA and the offset in FB of SB. 671*06c3fb27SDimitry Andric bool Reverse = false; 672*06c3fb27SDimitry Andric if (FA == FB) { 673*06c3fb27SDimitry Andric Reverse = SA.getOffset() < SB.getOffset(); 674*06c3fb27SDimitry Andric } else if (!isa<MCDummyFragment>(FA)) { 675*06c3fb27SDimitry Andric Reverse = std::find_if(std::next(FA->getIterator()), SecA.end(), 676*06c3fb27SDimitry Andric [&](auto &I) { return &I == FB; }) != SecA.end(); 677e8d8bef9SDimitry Andric } 6780b57cec5SDimitry Andric 679*06c3fb27SDimitry Andric uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset(); 680*06c3fb27SDimitry Andric int64_t Displacement = SA.getOffset() - SB.getOffset(); 681*06c3fb27SDimitry Andric if (Reverse) { 682*06c3fb27SDimitry Andric std::swap(FA, FB); 683*06c3fb27SDimitry Andric std::swap(SAOffset, SBOffset); 684*06c3fb27SDimitry Andric Displacement *= -1; 685e8d8bef9SDimitry Andric } 686*06c3fb27SDimitry Andric 687*06c3fb27SDimitry Andric [[maybe_unused]] bool Found = false; 688*06c3fb27SDimitry Andric // Track whether B is before a relaxable instruction and whether A is after 689*06c3fb27SDimitry Andric // a relaxable instruction. If SA and SB are separated by a linker-relaxable 690*06c3fb27SDimitry Andric // instruction, the difference cannot be resolved as it may be changed by 691*06c3fb27SDimitry Andric // the linker. 692*06c3fb27SDimitry Andric bool BBeforeRelax = false, AAfterRelax = false; 693*06c3fb27SDimitry Andric for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { 694*06c3fb27SDimitry Andric auto DF = dyn_cast<MCDataFragment>(FI); 695*06c3fb27SDimitry Andric if (DF && DF->isLinkerRelaxable()) { 696*06c3fb27SDimitry Andric if (&*FI != FB || SBOffset != DF->getContents().size()) 697*06c3fb27SDimitry Andric BBeforeRelax = true; 698*06c3fb27SDimitry Andric if (&*FI != FA || SAOffset == DF->getContents().size()) 699*06c3fb27SDimitry Andric AAfterRelax = true; 700*06c3fb27SDimitry Andric if (BBeforeRelax && AAfterRelax) 701*06c3fb27SDimitry Andric return; 702*06c3fb27SDimitry Andric } 703*06c3fb27SDimitry Andric if (&*FI == FA) { 704*06c3fb27SDimitry Andric Found = true; 705*06c3fb27SDimitry Andric break; 706*06c3fb27SDimitry Andric } 707*06c3fb27SDimitry Andric 708*06c3fb27SDimitry Andric int64_t Num; 709*06c3fb27SDimitry Andric if (DF) { 710*06c3fb27SDimitry Andric Displacement += DF->getContents().size(); 711*06c3fb27SDimitry Andric } else if (auto *FF = dyn_cast<MCFillFragment>(FI); 712*06c3fb27SDimitry Andric FF && FF->getNumValues().evaluateAsAbsolute(Num)) { 713*06c3fb27SDimitry Andric Displacement += Num * FF->getValueSize(); 714*06c3fb27SDimitry Andric } else { 715*06c3fb27SDimitry Andric return; 716*06c3fb27SDimitry Andric } 717*06c3fb27SDimitry Andric } 718*06c3fb27SDimitry Andric // If the previous loop does not find FA, FA must be a dummy fragment not in 719*06c3fb27SDimitry Andric // the fragment list (which means SA is a pending label (see 720*06c3fb27SDimitry Andric // flushPendingLabels)). In either case, we can resolve the difference. 721*06c3fb27SDimitry Andric assert(Found || isa<MCDummyFragment>(FA)); 722*06c3fb27SDimitry Andric Addend += Reverse ? -Displacement : Displacement; 723*06c3fb27SDimitry Andric FinalizeFolding(); 724e8d8bef9SDimitry Andric } 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric /// Evaluate the result of an add between (conceptually) two MCValues. 7280b57cec5SDimitry Andric /// 7290b57cec5SDimitry Andric /// This routine conceptually attempts to construct an MCValue: 7300b57cec5SDimitry Andric /// Result = (Result_A - Result_B + Result_Cst) 7310b57cec5SDimitry Andric /// from two MCValue's LHS and RHS where 7320b57cec5SDimitry Andric /// Result = LHS + RHS 7330b57cec5SDimitry Andric /// and 7340b57cec5SDimitry Andric /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 7350b57cec5SDimitry Andric /// 736480093f4SDimitry Andric /// This routine attempts to aggressively fold the operands such that the result 7370b57cec5SDimitry Andric /// is representable in an MCValue, but may not always succeed. 7380b57cec5SDimitry Andric /// 7390b57cec5SDimitry Andric /// \returns True on success, false if the result is not representable in an 7400b57cec5SDimitry Andric /// MCValue. 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric /// NOTE: It is really important to have both the Asm and Layout arguments. 7430b57cec5SDimitry Andric /// They might look redundant, but this function can be used before layout 7440b57cec5SDimitry Andric /// is done (see the object streamer for example) and having the Asm argument 7450b57cec5SDimitry Andric /// lets us avoid relaxations early. 7460b57cec5SDimitry Andric static bool 7470b57cec5SDimitry Andric EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, 7480b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, 7490b57cec5SDimitry Andric const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, 7500b57cec5SDimitry Andric int64_t RHS_Cst, MCValue &Res) { 7510b57cec5SDimitry Andric // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 7520b57cec5SDimitry Andric // about dealing with modifiers. This will ultimately bite us, one day. 7530b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 7540b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 7550b57cec5SDimitry Andric int64_t LHS_Cst = LHS.getConstant(); 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric // Fold the result constant immediately. 7580b57cec5SDimitry Andric int64_t Result_Cst = LHS_Cst + RHS_Cst; 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric assert((!Layout || Asm) && 7610b57cec5SDimitry Andric "Must have an assembler object if layout is given!"); 7620b57cec5SDimitry Andric 763fe6060f1SDimitry Andric // If we have a layout, we can fold resolved differences. 764fe6060f1SDimitry Andric if (Asm) { 7650b57cec5SDimitry Andric // First, fold out any differences which are fully resolved. By 7660b57cec5SDimitry Andric // reassociating terms in 7670b57cec5SDimitry Andric // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 7680b57cec5SDimitry Andric // we have the four possible differences: 7690b57cec5SDimitry Andric // (LHS_A - LHS_B), 7700b57cec5SDimitry Andric // (LHS_A - RHS_B), 7710b57cec5SDimitry Andric // (RHS_A - LHS_B), 7720b57cec5SDimitry Andric // (RHS_A - RHS_B). 7730b57cec5SDimitry Andric // Since we are attempting to be as aggressive as possible about folding, we 7740b57cec5SDimitry Andric // attempt to evaluate each possible alternative. 7750b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 7760b57cec5SDimitry Andric Result_Cst); 7770b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 7780b57cec5SDimitry Andric Result_Cst); 7790b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 7800b57cec5SDimitry Andric Result_Cst); 7810b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 7820b57cec5SDimitry Andric Result_Cst); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // We can't represent the addition or subtraction of two symbols. 7860b57cec5SDimitry Andric if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 7870b57cec5SDimitry Andric return false; 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric // At this point, we have at most one additive symbol and one subtractive 7900b57cec5SDimitry Andric // symbol -- find them. 7910b57cec5SDimitry Andric const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 7920b57cec5SDimitry Andric const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric Res = MCValue::get(A, B, Result_Cst); 7950b57cec5SDimitry Andric return true; 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatable(MCValue &Res, 7990b57cec5SDimitry Andric const MCAsmLayout *Layout, 8000b57cec5SDimitry Andric const MCFixup *Fixup) const { 8010b57cec5SDimitry Andric MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; 8020b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, 8030b57cec5SDimitry Andric false); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { 8070b57cec5SDimitry Andric MCAssembler *Assembler = &Layout.getAssembler(); 8080b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, 8090b57cec5SDimitry Andric true); 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric static bool canExpand(const MCSymbol &Sym, bool InSet) { 813*06c3fb27SDimitry Andric if (Sym.isWeakExternal()) 814*06c3fb27SDimitry Andric return false; 815*06c3fb27SDimitry Andric 8160b57cec5SDimitry Andric const MCExpr *Expr = Sym.getVariableValue(); 8170b57cec5SDimitry Andric const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); 8180b57cec5SDimitry Andric if (Inner) { 8190b57cec5SDimitry Andric if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) 8200b57cec5SDimitry Andric return false; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric if (InSet) 8240b57cec5SDimitry Andric return true; 8250b57cec5SDimitry Andric return !Sym.isInSection(); 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 8290b57cec5SDimitry Andric const MCAsmLayout *Layout, 8300b57cec5SDimitry Andric const MCFixup *Fixup, 8310b57cec5SDimitry Andric const SectionAddrMap *Addrs, 8320b57cec5SDimitry Andric bool InSet) const { 8330b57cec5SDimitry Andric ++stats::MCExprEvaluate; 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric switch (getKind()) { 8360b57cec5SDimitry Andric case Target: 8370b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, 8380b57cec5SDimitry Andric Fixup); 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric case Constant: 8410b57cec5SDimitry Andric Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 8420b57cec5SDimitry Andric return true; 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric case SymbolRef: { 8450b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 8460b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 847e8d8bef9SDimitry Andric const auto Kind = SRE->getKind(); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric // Evaluate recursively if this is a variable. 850e8d8bef9SDimitry Andric if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && 8510b57cec5SDimitry Andric canExpand(Sym, InSet)) { 8520b57cec5SDimitry Andric bool IsMachO = SRE->hasSubsectionsViaSymbols(); 8530b57cec5SDimitry Andric if (Sym.getVariableValue()->evaluateAsRelocatableImpl( 8540b57cec5SDimitry Andric Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { 855e8d8bef9SDimitry Andric if (Kind != MCSymbolRefExpr::VK_None) { 856e8d8bef9SDimitry Andric if (Res.isAbsolute()) { 857e8d8bef9SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 858e8d8bef9SDimitry Andric return true; 859e8d8bef9SDimitry Andric } 860e8d8bef9SDimitry Andric // If the reference has a variant kind, we can only handle expressions 861e8d8bef9SDimitry Andric // which evaluate exactly to a single unadorned symbol. Attach the 862e8d8bef9SDimitry Andric // original VariantKind to SymA of the result. 863e8d8bef9SDimitry Andric if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || 864e8d8bef9SDimitry Andric Res.getSymB() || Res.getConstant()) 865e8d8bef9SDimitry Andric return false; 866e8d8bef9SDimitry Andric Res = 867e8d8bef9SDimitry Andric MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), 868e8d8bef9SDimitry Andric Kind, Asm->getContext()), 869e8d8bef9SDimitry Andric Res.getSymB(), Res.getConstant(), Res.getRefKind()); 870e8d8bef9SDimitry Andric } 8710b57cec5SDimitry Andric if (!IsMachO) 8720b57cec5SDimitry Andric return true; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric const MCSymbolRefExpr *A = Res.getSymA(); 8750b57cec5SDimitry Andric const MCSymbolRefExpr *B = Res.getSymB(); 8760b57cec5SDimitry Andric // FIXME: This is small hack. Given 8770b57cec5SDimitry Andric // a = b + 4 8780b57cec5SDimitry Andric // .long a 8790b57cec5SDimitry Andric // the OS X assembler will completely drop the 4. We should probably 8800b57cec5SDimitry Andric // include it in the relocation or produce an error if that is not 8810b57cec5SDimitry Andric // possible. 8820b57cec5SDimitry Andric // Allow constant expressions. 8830b57cec5SDimitry Andric if (!A && !B) 8840b57cec5SDimitry Andric return true; 8850b57cec5SDimitry Andric // Allows aliases with zero offset. 8860b57cec5SDimitry Andric if (Res.getConstant() == 0 && (!A || !B)) 8870b57cec5SDimitry Andric return true; 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 8920b57cec5SDimitry Andric return true; 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric case Unary: { 8960b57cec5SDimitry Andric const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 8970b57cec5SDimitry Andric MCValue Value; 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, 9000b57cec5SDimitry Andric Addrs, InSet)) 9010b57cec5SDimitry Andric return false; 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric switch (AUE->getOpcode()) { 9040b57cec5SDimitry Andric case MCUnaryExpr::LNot: 9050b57cec5SDimitry Andric if (!Value.isAbsolute()) 9060b57cec5SDimitry Andric return false; 9070b57cec5SDimitry Andric Res = MCValue::get(!Value.getConstant()); 9080b57cec5SDimitry Andric break; 9090b57cec5SDimitry Andric case MCUnaryExpr::Minus: 9100b57cec5SDimitry Andric /// -(a - b + const) ==> (b - a - const) 9110b57cec5SDimitry Andric if (Value.getSymA() && !Value.getSymB()) 9120b57cec5SDimitry Andric return false; 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 9150b57cec5SDimitry Andric Res = MCValue::get(Value.getSymB(), Value.getSymA(), 9160b57cec5SDimitry Andric -(uint64_t)Value.getConstant()); 9170b57cec5SDimitry Andric break; 9180b57cec5SDimitry Andric case MCUnaryExpr::Not: 9190b57cec5SDimitry Andric if (!Value.isAbsolute()) 9200b57cec5SDimitry Andric return false; 9210b57cec5SDimitry Andric Res = MCValue::get(~Value.getConstant()); 9220b57cec5SDimitry Andric break; 9230b57cec5SDimitry Andric case MCUnaryExpr::Plus: 9240b57cec5SDimitry Andric Res = Value; 9250b57cec5SDimitry Andric break; 9260b57cec5SDimitry Andric } 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric return true; 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric case Binary: { 9320b57cec5SDimitry Andric const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 9330b57cec5SDimitry Andric MCValue LHSValue, RHSValue; 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, 9360b57cec5SDimitry Andric Addrs, InSet) || 9370b57cec5SDimitry Andric !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, 9380b57cec5SDimitry Andric Addrs, InSet)) { 9390b57cec5SDimitry Andric // Check if both are Target Expressions, see if we can compare them. 940*06c3fb27SDimitry Andric if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) { 941*06c3fb27SDimitry Andric const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS()); 9420b57cec5SDimitry Andric switch (ABE->getOpcode()) { 9430b57cec5SDimitry Andric case MCBinaryExpr::EQ: 944*06c3fb27SDimitry Andric Res = MCValue::get(L->isEqualTo(R) ? -1 : 0); 9450b57cec5SDimitry Andric return true; 9460b57cec5SDimitry Andric case MCBinaryExpr::NE: 947*06c3fb27SDimitry Andric Res = MCValue::get(L->isEqualTo(R) ? 0 : -1); 9480b57cec5SDimitry Andric return true; 949*06c3fb27SDimitry Andric default: 950*06c3fb27SDimitry Andric break; 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric } 9530b57cec5SDimitry Andric return false; 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric // We only support a few operations on non-constant expressions, handle 9570b57cec5SDimitry Andric // those first. 9580b57cec5SDimitry Andric if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 9590b57cec5SDimitry Andric switch (ABE->getOpcode()) { 9600b57cec5SDimitry Andric default: 9610b57cec5SDimitry Andric return false; 9620b57cec5SDimitry Andric case MCBinaryExpr::Sub: 9630b57cec5SDimitry Andric // Negate RHS and add. 9640b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 9650b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 9660b57cec5SDimitry Andric RHSValue.getSymB(), RHSValue.getSymA(), 9670b57cec5SDimitry Andric -(uint64_t)RHSValue.getConstant(), Res); 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric case MCBinaryExpr::Add: 9700b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 9710b57cec5SDimitry Andric RHSValue.getSymA(), RHSValue.getSymB(), 9720b57cec5SDimitry Andric RHSValue.getConstant(), Res); 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric // FIXME: We need target hooks for the evaluation. It may be limited in 9770b57cec5SDimitry Andric // width, and gas defines the result of comparisons differently from 9780b57cec5SDimitry Andric // Apple as. 9790b57cec5SDimitry Andric int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 9800b57cec5SDimitry Andric int64_t Result = 0; 9810b57cec5SDimitry Andric auto Op = ABE->getOpcode(); 9820b57cec5SDimitry Andric switch (Op) { 9830b57cec5SDimitry Andric case MCBinaryExpr::AShr: Result = LHS >> RHS; break; 9840b57cec5SDimitry Andric case MCBinaryExpr::Add: Result = LHS + RHS; break; 9850b57cec5SDimitry Andric case MCBinaryExpr::And: Result = LHS & RHS; break; 9860b57cec5SDimitry Andric case MCBinaryExpr::Div: 9870b57cec5SDimitry Andric case MCBinaryExpr::Mod: 9880b57cec5SDimitry Andric // Handle division by zero. gas just emits a warning and keeps going, 9890b57cec5SDimitry Andric // we try to be stricter. 9900b57cec5SDimitry Andric // FIXME: Currently the caller of this function has no way to understand 9910b57cec5SDimitry Andric // we're bailing out because of 'division by zero'. Therefore, it will 9920b57cec5SDimitry Andric // emit a 'expected relocatable expression' error. It would be nice to 9930b57cec5SDimitry Andric // change this code to emit a better diagnostic. 9940b57cec5SDimitry Andric if (RHS == 0) 9950b57cec5SDimitry Andric return false; 9960b57cec5SDimitry Andric if (ABE->getOpcode() == MCBinaryExpr::Div) 9970b57cec5SDimitry Andric Result = LHS / RHS; 9980b57cec5SDimitry Andric else 9990b57cec5SDimitry Andric Result = LHS % RHS; 10000b57cec5SDimitry Andric break; 10010b57cec5SDimitry Andric case MCBinaryExpr::EQ: Result = LHS == RHS; break; 10020b57cec5SDimitry Andric case MCBinaryExpr::GT: Result = LHS > RHS; break; 10030b57cec5SDimitry Andric case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 10040b57cec5SDimitry Andric case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 10050b57cec5SDimitry Andric case MCBinaryExpr::LOr: Result = LHS || RHS; break; 10060b57cec5SDimitry Andric case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; 10070b57cec5SDimitry Andric case MCBinaryExpr::LT: Result = LHS < RHS; break; 10080b57cec5SDimitry Andric case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 10090b57cec5SDimitry Andric case MCBinaryExpr::Mul: Result = LHS * RHS; break; 10100b57cec5SDimitry Andric case MCBinaryExpr::NE: Result = LHS != RHS; break; 10110b57cec5SDimitry Andric case MCBinaryExpr::Or: Result = LHS | RHS; break; 1012e8d8bef9SDimitry Andric case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; 10130b57cec5SDimitry Andric case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; 10140b57cec5SDimitry Andric case MCBinaryExpr::Sub: Result = LHS - RHS; break; 10150b57cec5SDimitry Andric case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric switch (Op) { 10190b57cec5SDimitry Andric default: 10200b57cec5SDimitry Andric Res = MCValue::get(Result); 10210b57cec5SDimitry Andric break; 10220b57cec5SDimitry Andric case MCBinaryExpr::EQ: 10230b57cec5SDimitry Andric case MCBinaryExpr::GT: 10240b57cec5SDimitry Andric case MCBinaryExpr::GTE: 10250b57cec5SDimitry Andric case MCBinaryExpr::LT: 10260b57cec5SDimitry Andric case MCBinaryExpr::LTE: 10270b57cec5SDimitry Andric case MCBinaryExpr::NE: 10280b57cec5SDimitry Andric // A comparison operator returns a -1 if true and 0 if false. 10290b57cec5SDimitry Andric Res = MCValue::get(Result ? -1 : 0); 10300b57cec5SDimitry Andric break; 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric return true; 10340b57cec5SDimitry Andric } 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric MCFragment *MCExpr::findAssociatedFragment() const { 10410b57cec5SDimitry Andric switch (getKind()) { 10420b57cec5SDimitry Andric case Target: 10430b57cec5SDimitry Andric // We never look through target specific expressions. 10440b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->findAssociatedFragment(); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric case Constant: 10470b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric case SymbolRef: { 10500b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 10510b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 10520b57cec5SDimitry Andric return Sym.getFragment(); 10530b57cec5SDimitry Andric } 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric case Unary: 10560b57cec5SDimitry Andric return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric case Binary: { 10590b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 10600b57cec5SDimitry Andric MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); 10610b57cec5SDimitry Andric MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric // If either is absolute, return the other. 10640b57cec5SDimitry Andric if (LHS_F == MCSymbol::AbsolutePseudoFragment) 10650b57cec5SDimitry Andric return RHS_F; 10660b57cec5SDimitry Andric if (RHS_F == MCSymbol::AbsolutePseudoFragment) 10670b57cec5SDimitry Andric return LHS_F; 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric // Not always correct, but probably the best we can do without more context. 10700b57cec5SDimitry Andric if (BE->getOpcode() == MCBinaryExpr::Sub) 10710b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric // Otherwise, return the first non-null fragment. 10740b57cec5SDimitry Andric return LHS_F ? LHS_F : RHS_F; 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 10790b57cec5SDimitry Andric } 1080