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*5f757f3fSDimitry Andric case VK_PPC_AIX_TLSIE: 331*5f757f3fSDimitry Andric return "ie"; 33206c3fb27SDimitry Andric case VK_PPC_AIX_TLSLE: 33306c3fb27SDimitry Andric return "le"; 3340b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD: return "got@tlsld"; 3350b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 3360b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; 3370b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 3385ffd83dbSDimitry Andric case VK_PPC_GOT_PCREL: 3395ffd83dbSDimitry Andric return "got@pcrel"; 340e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSGD_PCREL: 341e8d8bef9SDimitry Andric return "got@tlsgd@pcrel"; 342e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSLD_PCREL: 343e8d8bef9SDimitry Andric return "got@tlsld@pcrel"; 344e8d8bef9SDimitry Andric case VK_PPC_GOT_TPREL_PCREL: 345e8d8bef9SDimitry Andric return "got@tprel@pcrel"; 346e8d8bef9SDimitry Andric case VK_PPC_TLS_PCREL: 347e8d8bef9SDimitry Andric return "tls@pcrel"; 3480b57cec5SDimitry Andric case VK_PPC_TLSLD: return "tlsld"; 3490b57cec5SDimitry Andric case VK_PPC_LOCAL: return "local"; 3505ffd83dbSDimitry Andric case VK_PPC_NOTOC: return "notoc"; 351e8d8bef9SDimitry Andric case VK_PPC_PCREL_OPT: return "<<invalid>>"; 3520b57cec5SDimitry Andric case VK_COFF_IMGREL32: return "IMGREL"; 3530b57cec5SDimitry Andric case VK_Hexagon_LO16: return "LO16"; 3540b57cec5SDimitry Andric case VK_Hexagon_HI16: return "HI16"; 3550b57cec5SDimitry Andric case VK_Hexagon_GPREL: return "GPREL"; 3560b57cec5SDimitry Andric case VK_Hexagon_GD_GOT: return "GDGOT"; 3570b57cec5SDimitry Andric case VK_Hexagon_LD_GOT: return "LDGOT"; 3580b57cec5SDimitry Andric case VK_Hexagon_GD_PLT: return "GDPLT"; 3590b57cec5SDimitry Andric case VK_Hexagon_LD_PLT: return "LDPLT"; 3600b57cec5SDimitry Andric case VK_Hexagon_IE: return "IE"; 3610b57cec5SDimitry Andric case VK_Hexagon_IE_GOT: return "IEGOT"; 3620b57cec5SDimitry Andric case VK_WASM_TYPEINDEX: return "TYPEINDEX"; 3630b57cec5SDimitry Andric case VK_WASM_MBREL: return "MBREL"; 364e8d8bef9SDimitry Andric case VK_WASM_TLSREL: return "TLSREL"; 3650b57cec5SDimitry Andric case VK_WASM_TBREL: return "TBREL"; 366349cc55cSDimitry Andric case VK_WASM_GOT_TLS: return "GOT@TLS"; 36706c3fb27SDimitry Andric case VK_WASM_FUNCINDEX: return "FUNCINDEX"; 3680b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; 3690b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; 3700b57cec5SDimitry Andric case VK_AMDGPU_REL32_LO: return "rel32@lo"; 3710b57cec5SDimitry Andric case VK_AMDGPU_REL32_HI: return "rel32@hi"; 3720b57cec5SDimitry Andric case VK_AMDGPU_REL64: return "rel64"; 3730b57cec5SDimitry Andric case VK_AMDGPU_ABS32_LO: return "abs32@lo"; 3740b57cec5SDimitry Andric case VK_AMDGPU_ABS32_HI: return "abs32@hi"; 3755ffd83dbSDimitry Andric case VK_VE_HI32: return "hi"; 3765ffd83dbSDimitry Andric case VK_VE_LO32: return "lo"; 3775ffd83dbSDimitry Andric case VK_VE_PC_HI32: return "pc_hi"; 3785ffd83dbSDimitry Andric case VK_VE_PC_LO32: return "pc_lo"; 3795ffd83dbSDimitry Andric case VK_VE_GOT_HI32: return "got_hi"; 3805ffd83dbSDimitry Andric case VK_VE_GOT_LO32: return "got_lo"; 3815ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: return "gotoff_hi"; 3825ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: return "gotoff_lo"; 3835ffd83dbSDimitry Andric case VK_VE_PLT_HI32: return "plt_hi"; 3845ffd83dbSDimitry Andric case VK_VE_PLT_LO32: return "plt_lo"; 3855ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: return "tls_gd_hi"; 3865ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: return "tls_gd_lo"; 3875ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: return "tpoff_hi"; 3885ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: return "tpoff_lo"; 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric llvm_unreachable("Invalid variant kind"); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind 3940b57cec5SDimitry Andric MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 3950b57cec5SDimitry Andric return StringSwitch<VariantKind>(Name.lower()) 3960b57cec5SDimitry Andric .Case("dtprel", VK_DTPREL) 3970b57cec5SDimitry Andric .Case("dtpoff", VK_DTPOFF) 3980b57cec5SDimitry Andric .Case("got", VK_GOT) 3990b57cec5SDimitry Andric .Case("gotoff", VK_GOTOFF) 4000b57cec5SDimitry Andric .Case("gotrel", VK_GOTREL) 4015ffd83dbSDimitry Andric .Case("pcrel", VK_PCREL) 4020b57cec5SDimitry Andric .Case("gotpcrel", VK_GOTPCREL) 403349cc55cSDimitry Andric .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX) 4040b57cec5SDimitry Andric .Case("gottpoff", VK_GOTTPOFF) 4050b57cec5SDimitry Andric .Case("indntpoff", VK_INDNTPOFF) 4060b57cec5SDimitry Andric .Case("ntpoff", VK_NTPOFF) 4070b57cec5SDimitry Andric .Case("gotntpoff", VK_GOTNTPOFF) 4080b57cec5SDimitry Andric .Case("plt", VK_PLT) 4090b57cec5SDimitry Andric .Case("tlscall", VK_TLSCALL) 4100b57cec5SDimitry Andric .Case("tlsdesc", VK_TLSDESC) 4110b57cec5SDimitry Andric .Case("tlsgd", VK_TLSGD) 4120b57cec5SDimitry Andric .Case("tlsld", VK_TLSLD) 4130b57cec5SDimitry Andric .Case("tlsldm", VK_TLSLDM) 4140b57cec5SDimitry Andric .Case("tpoff", VK_TPOFF) 4150b57cec5SDimitry Andric .Case("tprel", VK_TPREL) 4160b57cec5SDimitry Andric .Case("tlvp", VK_TLVP) 4170b57cec5SDimitry Andric .Case("tlvppage", VK_TLVPPAGE) 4180b57cec5SDimitry Andric .Case("tlvppageoff", VK_TLVPPAGEOFF) 4190b57cec5SDimitry Andric .Case("page", VK_PAGE) 4200b57cec5SDimitry Andric .Case("pageoff", VK_PAGEOFF) 4210b57cec5SDimitry Andric .Case("gotpage", VK_GOTPAGE) 4220b57cec5SDimitry Andric .Case("gotpageoff", VK_GOTPAGEOFF) 4230b57cec5SDimitry Andric .Case("imgrel", VK_COFF_IMGREL32) 4240b57cec5SDimitry Andric .Case("secrel32", VK_SECREL) 4250b57cec5SDimitry Andric .Case("size", VK_SIZE) 4260b57cec5SDimitry Andric .Case("abs8", VK_X86_ABS8) 427e8d8bef9SDimitry Andric .Case("pltoff", VK_X86_PLTOFF) 4280b57cec5SDimitry Andric .Case("l", VK_PPC_LO) 4290b57cec5SDimitry Andric .Case("h", VK_PPC_HI) 4300b57cec5SDimitry Andric .Case("ha", VK_PPC_HA) 4310b57cec5SDimitry Andric .Case("high", VK_PPC_HIGH) 4320b57cec5SDimitry Andric .Case("higha", VK_PPC_HIGHA) 4330b57cec5SDimitry Andric .Case("higher", VK_PPC_HIGHER) 4340b57cec5SDimitry Andric .Case("highera", VK_PPC_HIGHERA) 4350b57cec5SDimitry Andric .Case("highest", VK_PPC_HIGHEST) 4360b57cec5SDimitry Andric .Case("highesta", VK_PPC_HIGHESTA) 4370b57cec5SDimitry Andric .Case("got@l", VK_PPC_GOT_LO) 4380b57cec5SDimitry Andric .Case("got@h", VK_PPC_GOT_HI) 4390b57cec5SDimitry Andric .Case("got@ha", VK_PPC_GOT_HA) 4400b57cec5SDimitry Andric .Case("local", VK_PPC_LOCAL) 4410b57cec5SDimitry Andric .Case("tocbase", VK_PPC_TOCBASE) 4420b57cec5SDimitry Andric .Case("toc", VK_PPC_TOC) 4430b57cec5SDimitry Andric .Case("toc@l", VK_PPC_TOC_LO) 4440b57cec5SDimitry Andric .Case("toc@h", VK_PPC_TOC_HI) 4450b57cec5SDimitry Andric .Case("toc@ha", VK_PPC_TOC_HA) 4468bcb0991SDimitry Andric .Case("u", VK_PPC_U) 4478bcb0991SDimitry Andric .Case("l", VK_PPC_L) 4480b57cec5SDimitry Andric .Case("tls", VK_PPC_TLS) 4490b57cec5SDimitry Andric .Case("dtpmod", VK_PPC_DTPMOD) 4500b57cec5SDimitry Andric .Case("tprel@l", VK_PPC_TPREL_LO) 4510b57cec5SDimitry Andric .Case("tprel@h", VK_PPC_TPREL_HI) 4520b57cec5SDimitry Andric .Case("tprel@ha", VK_PPC_TPREL_HA) 4530b57cec5SDimitry Andric .Case("tprel@high", VK_PPC_TPREL_HIGH) 4540b57cec5SDimitry Andric .Case("tprel@higha", VK_PPC_TPREL_HIGHA) 4550b57cec5SDimitry Andric .Case("tprel@higher", VK_PPC_TPREL_HIGHER) 4560b57cec5SDimitry Andric .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) 4570b57cec5SDimitry Andric .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) 4580b57cec5SDimitry Andric .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) 4590b57cec5SDimitry Andric .Case("dtprel@l", VK_PPC_DTPREL_LO) 4600b57cec5SDimitry Andric .Case("dtprel@h", VK_PPC_DTPREL_HI) 4610b57cec5SDimitry Andric .Case("dtprel@ha", VK_PPC_DTPREL_HA) 4620b57cec5SDimitry Andric .Case("dtprel@high", VK_PPC_DTPREL_HIGH) 4630b57cec5SDimitry Andric .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) 4640b57cec5SDimitry Andric .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) 4650b57cec5SDimitry Andric .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) 4660b57cec5SDimitry Andric .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) 4670b57cec5SDimitry Andric .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) 4680b57cec5SDimitry Andric .Case("got@tprel", VK_PPC_GOT_TPREL) 4690b57cec5SDimitry Andric .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 4700b57cec5SDimitry Andric .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) 4710b57cec5SDimitry Andric .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 4720b57cec5SDimitry Andric .Case("got@dtprel", VK_PPC_GOT_DTPREL) 4730b57cec5SDimitry Andric .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) 4740b57cec5SDimitry Andric .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) 4750b57cec5SDimitry Andric .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) 4760b57cec5SDimitry Andric .Case("got@tlsgd", VK_PPC_GOT_TLSGD) 4770b57cec5SDimitry Andric .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 4780b57cec5SDimitry Andric .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) 4790b57cec5SDimitry Andric .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 4800b57cec5SDimitry Andric .Case("got@tlsld", VK_PPC_GOT_TLSLD) 4810b57cec5SDimitry Andric .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 4820b57cec5SDimitry Andric .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) 4830b57cec5SDimitry Andric .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 4845ffd83dbSDimitry Andric .Case("got@pcrel", VK_PPC_GOT_PCREL) 485e8d8bef9SDimitry Andric .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) 486e8d8bef9SDimitry Andric .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) 487e8d8bef9SDimitry Andric .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) 488e8d8bef9SDimitry Andric .Case("tls@pcrel", VK_PPC_TLS_PCREL) 4895ffd83dbSDimitry Andric .Case("notoc", VK_PPC_NOTOC) 4900b57cec5SDimitry Andric .Case("gdgot", VK_Hexagon_GD_GOT) 4910b57cec5SDimitry Andric .Case("gdplt", VK_Hexagon_GD_PLT) 4920b57cec5SDimitry Andric .Case("iegot", VK_Hexagon_IE_GOT) 4930b57cec5SDimitry Andric .Case("ie", VK_Hexagon_IE) 4940b57cec5SDimitry Andric .Case("ldgot", VK_Hexagon_LD_GOT) 4950b57cec5SDimitry Andric .Case("ldplt", VK_Hexagon_LD_PLT) 4960b57cec5SDimitry Andric .Case("none", VK_ARM_NONE) 4970b57cec5SDimitry Andric .Case("got_prel", VK_ARM_GOT_PREL) 4980b57cec5SDimitry Andric .Case("target1", VK_ARM_TARGET1) 4990b57cec5SDimitry Andric .Case("target2", VK_ARM_TARGET2) 5000b57cec5SDimitry Andric .Case("prel31", VK_ARM_PREL31) 5010b57cec5SDimitry Andric .Case("sbrel", VK_ARM_SBREL) 5020b57cec5SDimitry Andric .Case("tlsldo", VK_ARM_TLSLDO) 5030b57cec5SDimitry Andric .Case("lo8", VK_AVR_LO8) 5040b57cec5SDimitry Andric .Case("hi8", VK_AVR_HI8) 5050b57cec5SDimitry Andric .Case("hlo8", VK_AVR_HLO8) 5060b57cec5SDimitry Andric .Case("typeindex", VK_WASM_TYPEINDEX) 5070b57cec5SDimitry Andric .Case("tbrel", VK_WASM_TBREL) 5080b57cec5SDimitry Andric .Case("mbrel", VK_WASM_MBREL) 509e8d8bef9SDimitry Andric .Case("tlsrel", VK_WASM_TLSREL) 510349cc55cSDimitry Andric .Case("got@tls", VK_WASM_GOT_TLS) 51106c3fb27SDimitry Andric .Case("funcindex", VK_WASM_FUNCINDEX) 5120b57cec5SDimitry Andric .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) 5130b57cec5SDimitry Andric .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) 5140b57cec5SDimitry Andric .Case("rel32@lo", VK_AMDGPU_REL32_LO) 5150b57cec5SDimitry Andric .Case("rel32@hi", VK_AMDGPU_REL32_HI) 5160b57cec5SDimitry Andric .Case("rel64", VK_AMDGPU_REL64) 5170b57cec5SDimitry Andric .Case("abs32@lo", VK_AMDGPU_ABS32_LO) 5180b57cec5SDimitry Andric .Case("abs32@hi", VK_AMDGPU_ABS32_HI) 5195ffd83dbSDimitry Andric .Case("hi", VK_VE_HI32) 5205ffd83dbSDimitry Andric .Case("lo", VK_VE_LO32) 5215ffd83dbSDimitry Andric .Case("pc_hi", VK_VE_PC_HI32) 5225ffd83dbSDimitry Andric .Case("pc_lo", VK_VE_PC_LO32) 5235ffd83dbSDimitry Andric .Case("got_hi", VK_VE_GOT_HI32) 5245ffd83dbSDimitry Andric .Case("got_lo", VK_VE_GOT_LO32) 5255ffd83dbSDimitry Andric .Case("gotoff_hi", VK_VE_GOTOFF_HI32) 5265ffd83dbSDimitry Andric .Case("gotoff_lo", VK_VE_GOTOFF_LO32) 5275ffd83dbSDimitry Andric .Case("plt_hi", VK_VE_PLT_HI32) 5285ffd83dbSDimitry Andric .Case("plt_lo", VK_VE_PLT_LO32) 5295ffd83dbSDimitry Andric .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) 5305ffd83dbSDimitry Andric .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) 5315ffd83dbSDimitry Andric .Case("tpoff_hi", VK_VE_TPOFF_HI32) 5325ffd83dbSDimitry Andric .Case("tpoff_lo", VK_VE_TPOFF_LO32) 5330b57cec5SDimitry Andric .Default(VK_Invalid); 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric /* *** */ 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric void MCTargetExpr::anchor() {} 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric /* *** */ 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { 5438bcb0991SDimitry Andric return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5470b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5488bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5520b57cec5SDimitry Andric const MCAsmLayout &Layout, 5530b57cec5SDimitry Andric const SectionAddrMap &Addrs) const { 5548bcb0991SDimitry Andric // Setting InSet causes us to absolutize differences across sections and that 5558bcb0991SDimitry Andric // is what the MachO writer uses Addrs for. 5568bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 5608bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { 5648bcb0991SDimitry Andric return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric bool MCExpr::evaluateKnownAbsolute(int64_t &Res, 5680b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5690b57cec5SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, 5700b57cec5SDimitry Andric true); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 5740b57cec5SDimitry Andric const MCAsmLayout *Layout, 5750b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet) const { 5760b57cec5SDimitry Andric MCValue Value; 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric // Fast path constants. 5790b57cec5SDimitry Andric if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 5800b57cec5SDimitry Andric Res = CE->getValue(); 5810b57cec5SDimitry Andric return true; 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric bool IsRelocatable = 5850b57cec5SDimitry Andric evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // Record the current value. 5880b57cec5SDimitry Andric Res = Value.getConstant(); 5890b57cec5SDimitry Andric 5900b57cec5SDimitry Andric return IsRelocatable && Value.isAbsolute(); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric /// Helper method for \see EvaluateSymbolAdd(). 5940b57cec5SDimitry Andric static void AttemptToFoldSymbolOffsetDifference( 5950b57cec5SDimitry Andric const MCAssembler *Asm, const MCAsmLayout *Layout, 5960b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, 5970b57cec5SDimitry Andric const MCSymbolRefExpr *&B, int64_t &Addend) { 5980b57cec5SDimitry Andric if (!A || !B) 5990b57cec5SDimitry Andric return; 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric const MCSymbol &SA = A->getSymbol(); 6020b57cec5SDimitry Andric const MCSymbol &SB = B->getSymbol(); 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric if (SA.isUndefined() || SB.isUndefined()) 6050b57cec5SDimitry Andric return; 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 6080b57cec5SDimitry Andric return; 6090b57cec5SDimitry Andric 610e8d8bef9SDimitry Andric auto FinalizeFolding = [&]() { 6110b57cec5SDimitry Andric // Pointers to Thumb symbols need to have their low-bit set to allow 6120b57cec5SDimitry Andric // for interworking. 6130b57cec5SDimitry Andric if (Asm->isThumbFunc(&SA)) 6140b57cec5SDimitry Andric Addend |= 1; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric // Clear the symbol expr pointers to indicate we have folded these 6170b57cec5SDimitry Andric // operands. 6180b57cec5SDimitry Andric A = B = nullptr; 619e8d8bef9SDimitry Andric }; 6200b57cec5SDimitry Andric 621e8d8bef9SDimitry Andric const MCFragment *FA = SA.getFragment(); 622e8d8bef9SDimitry Andric const MCFragment *FB = SB.getFragment(); 6235ffd83dbSDimitry Andric const MCSection &SecA = *FA->getParent(); 6245ffd83dbSDimitry Andric const MCSection &SecB = *FB->getParent(); 6250b57cec5SDimitry Andric if ((&SecA != &SecB) && !Addrs) 6260b57cec5SDimitry Andric return; 6270b57cec5SDimitry Andric 62806c3fb27SDimitry Andric // When layout is available, we can generally compute the difference using the 62906c3fb27SDimitry Andric // getSymbolOffset path, which also avoids the possible slow fragment walk. 63006c3fb27SDimitry Andric // However, linker relaxation may cause incorrect fold of A-B if A and B are 63106c3fb27SDimitry Andric // separated by a linker-relaxable instruction. If the section contains 63206c3fb27SDimitry Andric // instructions and InSet is false (not expressions in directive like 63306c3fb27SDimitry Andric // .size/.fill), disable the fast path. 63406c3fb27SDimitry Andric if (Layout && (InSet || !SecA.hasInstructions() || 63506c3fb27SDimitry Andric !Asm->getContext().getTargetTriple().isRISCV())) { 63606c3fb27SDimitry Andric // If both symbols are in the same fragment, return the difference of their 63706c3fb27SDimitry Andric // offsets. canGetFragmentOffset(FA) may be false. 63806c3fb27SDimitry Andric if (FA == FB && !SA.isVariable() && !SB.isVariable()) { 63906c3fb27SDimitry Andric Addend += SA.getOffset() - SB.getOffset(); 64006c3fb27SDimitry Andric return FinalizeFolding(); 64106c3fb27SDimitry Andric } 6425ffd83dbSDimitry Andric // One of the symbol involved is part of a fragment being laid out. Quit now 6435ffd83dbSDimitry Andric // to avoid a self loop. 6445ffd83dbSDimitry Andric if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB)) 6455ffd83dbSDimitry Andric return; 6465ffd83dbSDimitry Andric 647e8d8bef9SDimitry Andric // Eagerly evaluate when layout is finalized. 6480b57cec5SDimitry Andric Addend += Layout->getSymbolOffset(A->getSymbol()) - 6490b57cec5SDimitry Andric Layout->getSymbolOffset(B->getSymbol()); 6500b57cec5SDimitry Andric if (Addrs && (&SecA != &SecB)) 6510b57cec5SDimitry Andric Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 6520b57cec5SDimitry Andric 653e8d8bef9SDimitry Andric FinalizeFolding(); 654e8d8bef9SDimitry Andric } else { 655e8d8bef9SDimitry Andric // When layout is not finalized, our ability to resolve differences between 656e8d8bef9SDimitry Andric // symbols is limited to specific cases where the fragments between two 657e8d8bef9SDimitry Andric // symbols (including the fragments the symbols are defined in) are 658e8d8bef9SDimitry Andric // fixed-size fragments so the difference can be calculated. For example, 659e8d8bef9SDimitry Andric // this is important when the Subtarget is changed and a new MCDataFragment 660e8d8bef9SDimitry Andric // is created in the case of foo: instr; .arch_extension ext; instr .if . - 661e8d8bef9SDimitry Andric // foo. 66206c3fb27SDimitry Andric if (SA.isVariable() || SB.isVariable() || 663e8d8bef9SDimitry Andric FA->getSubsectionNumber() != FB->getSubsectionNumber()) 664e8d8bef9SDimitry Andric return; 66506c3fb27SDimitry Andric 666e8d8bef9SDimitry Andric // Try to find a constant displacement from FA to FB, add the displacement 667e8d8bef9SDimitry Andric // between the offset in FA of SA and the offset in FB of SB. 66806c3fb27SDimitry Andric bool Reverse = false; 66906c3fb27SDimitry Andric if (FA == FB) { 67006c3fb27SDimitry Andric Reverse = SA.getOffset() < SB.getOffset(); 67106c3fb27SDimitry Andric } else if (!isa<MCDummyFragment>(FA)) { 67206c3fb27SDimitry Andric Reverse = std::find_if(std::next(FA->getIterator()), SecA.end(), 67306c3fb27SDimitry Andric [&](auto &I) { return &I == FB; }) != SecA.end(); 674e8d8bef9SDimitry Andric } 6750b57cec5SDimitry Andric 67606c3fb27SDimitry Andric uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset(); 67706c3fb27SDimitry Andric int64_t Displacement = SA.getOffset() - SB.getOffset(); 67806c3fb27SDimitry Andric if (Reverse) { 67906c3fb27SDimitry Andric std::swap(FA, FB); 68006c3fb27SDimitry Andric std::swap(SAOffset, SBOffset); 68106c3fb27SDimitry Andric Displacement *= -1; 682e8d8bef9SDimitry Andric } 68306c3fb27SDimitry Andric 68406c3fb27SDimitry Andric [[maybe_unused]] bool Found = false; 68506c3fb27SDimitry Andric // Track whether B is before a relaxable instruction and whether A is after 68606c3fb27SDimitry Andric // a relaxable instruction. If SA and SB are separated by a linker-relaxable 68706c3fb27SDimitry Andric // instruction, the difference cannot be resolved as it may be changed by 68806c3fb27SDimitry Andric // the linker. 68906c3fb27SDimitry Andric bool BBeforeRelax = false, AAfterRelax = false; 69006c3fb27SDimitry Andric for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { 69106c3fb27SDimitry Andric auto DF = dyn_cast<MCDataFragment>(FI); 69206c3fb27SDimitry Andric if (DF && DF->isLinkerRelaxable()) { 69306c3fb27SDimitry Andric if (&*FI != FB || SBOffset != DF->getContents().size()) 69406c3fb27SDimitry Andric BBeforeRelax = true; 69506c3fb27SDimitry Andric if (&*FI != FA || SAOffset == DF->getContents().size()) 69606c3fb27SDimitry Andric AAfterRelax = true; 69706c3fb27SDimitry Andric if (BBeforeRelax && AAfterRelax) 69806c3fb27SDimitry Andric return; 69906c3fb27SDimitry Andric } 70006c3fb27SDimitry Andric if (&*FI == FA) { 70106c3fb27SDimitry Andric Found = true; 70206c3fb27SDimitry Andric break; 70306c3fb27SDimitry Andric } 70406c3fb27SDimitry Andric 70506c3fb27SDimitry Andric int64_t Num; 70606c3fb27SDimitry Andric if (DF) { 70706c3fb27SDimitry Andric Displacement += DF->getContents().size(); 70806c3fb27SDimitry Andric } else if (auto *FF = dyn_cast<MCFillFragment>(FI); 70906c3fb27SDimitry Andric FF && FF->getNumValues().evaluateAsAbsolute(Num)) { 71006c3fb27SDimitry Andric Displacement += Num * FF->getValueSize(); 71106c3fb27SDimitry Andric } else { 71206c3fb27SDimitry Andric return; 71306c3fb27SDimitry Andric } 71406c3fb27SDimitry Andric } 71506c3fb27SDimitry Andric // If the previous loop does not find FA, FA must be a dummy fragment not in 71606c3fb27SDimitry Andric // the fragment list (which means SA is a pending label (see 71706c3fb27SDimitry Andric // flushPendingLabels)). In either case, we can resolve the difference. 71806c3fb27SDimitry Andric assert(Found || isa<MCDummyFragment>(FA)); 71906c3fb27SDimitry Andric Addend += Reverse ? -Displacement : Displacement; 72006c3fb27SDimitry Andric FinalizeFolding(); 721e8d8bef9SDimitry Andric } 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric /// Evaluate the result of an add between (conceptually) two MCValues. 7250b57cec5SDimitry Andric /// 7260b57cec5SDimitry Andric /// This routine conceptually attempts to construct an MCValue: 7270b57cec5SDimitry Andric /// Result = (Result_A - Result_B + Result_Cst) 7280b57cec5SDimitry Andric /// from two MCValue's LHS and RHS where 7290b57cec5SDimitry Andric /// Result = LHS + RHS 7300b57cec5SDimitry Andric /// and 7310b57cec5SDimitry Andric /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 7320b57cec5SDimitry Andric /// 733480093f4SDimitry Andric /// This routine attempts to aggressively fold the operands such that the result 7340b57cec5SDimitry Andric /// is representable in an MCValue, but may not always succeed. 7350b57cec5SDimitry Andric /// 7360b57cec5SDimitry Andric /// \returns True on success, false if the result is not representable in an 7370b57cec5SDimitry Andric /// MCValue. 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric /// NOTE: It is really important to have both the Asm and Layout arguments. 7400b57cec5SDimitry Andric /// They might look redundant, but this function can be used before layout 7410b57cec5SDimitry Andric /// is done (see the object streamer for example) and having the Asm argument 7420b57cec5SDimitry Andric /// lets us avoid relaxations early. 743*5f757f3fSDimitry Andric static bool EvaluateSymbolicAdd(const MCAssembler *Asm, 744*5f757f3fSDimitry Andric const MCAsmLayout *Layout, 745*5f757f3fSDimitry Andric const SectionAddrMap *Addrs, bool InSet, 746*5f757f3fSDimitry Andric const MCValue &LHS, const MCValue &RHS, 747*5f757f3fSDimitry Andric MCValue &Res) { 7480b57cec5SDimitry Andric // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 7490b57cec5SDimitry Andric // about dealing with modifiers. This will ultimately bite us, one day. 7500b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 7510b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 7520b57cec5SDimitry Andric int64_t LHS_Cst = LHS.getConstant(); 7530b57cec5SDimitry Andric 754*5f757f3fSDimitry Andric const MCSymbolRefExpr *RHS_A = RHS.getSymA(); 755*5f757f3fSDimitry Andric const MCSymbolRefExpr *RHS_B = RHS.getSymB(); 756*5f757f3fSDimitry Andric int64_t RHS_Cst = RHS.getConstant(); 757*5f757f3fSDimitry Andric 758*5f757f3fSDimitry Andric if (LHS.getRefKind() != RHS.getRefKind()) 759*5f757f3fSDimitry Andric return false; 760*5f757f3fSDimitry Andric 7610b57cec5SDimitry Andric // Fold the result constant immediately. 7620b57cec5SDimitry Andric int64_t Result_Cst = LHS_Cst + RHS_Cst; 7630b57cec5SDimitry Andric 7640b57cec5SDimitry Andric assert((!Layout || Asm) && 7650b57cec5SDimitry Andric "Must have an assembler object if layout is given!"); 7660b57cec5SDimitry Andric 767fe6060f1SDimitry Andric // If we have a layout, we can fold resolved differences. 768fe6060f1SDimitry Andric if (Asm) { 7690b57cec5SDimitry Andric // First, fold out any differences which are fully resolved. By 7700b57cec5SDimitry Andric // reassociating terms in 7710b57cec5SDimitry Andric // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 7720b57cec5SDimitry Andric // we have the four possible differences: 7730b57cec5SDimitry Andric // (LHS_A - LHS_B), 7740b57cec5SDimitry Andric // (LHS_A - RHS_B), 7750b57cec5SDimitry Andric // (RHS_A - LHS_B), 7760b57cec5SDimitry Andric // (RHS_A - RHS_B). 7770b57cec5SDimitry Andric // Since we are attempting to be as aggressive as possible about folding, we 7780b57cec5SDimitry Andric // attempt to evaluate each possible alternative. 7790b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 7800b57cec5SDimitry Andric Result_Cst); 7810b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 7820b57cec5SDimitry Andric Result_Cst); 7830b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 7840b57cec5SDimitry Andric Result_Cst); 7850b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 7860b57cec5SDimitry Andric Result_Cst); 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric // We can't represent the addition or subtraction of two symbols. 7900b57cec5SDimitry Andric if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 7910b57cec5SDimitry Andric return false; 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric // At this point, we have at most one additive symbol and one subtractive 7940b57cec5SDimitry Andric // symbol -- find them. 7950b57cec5SDimitry Andric const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 7960b57cec5SDimitry Andric const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric Res = MCValue::get(A, B, Result_Cst); 7990b57cec5SDimitry Andric return true; 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatable(MCValue &Res, 8030b57cec5SDimitry Andric const MCAsmLayout *Layout, 8040b57cec5SDimitry Andric const MCFixup *Fixup) const { 8050b57cec5SDimitry Andric MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; 8060b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, 8070b57cec5SDimitry Andric false); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { 8110b57cec5SDimitry Andric MCAssembler *Assembler = &Layout.getAssembler(); 8120b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, 8130b57cec5SDimitry Andric true); 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric static bool canExpand(const MCSymbol &Sym, bool InSet) { 81706c3fb27SDimitry Andric if (Sym.isWeakExternal()) 81806c3fb27SDimitry Andric return false; 81906c3fb27SDimitry Andric 8200b57cec5SDimitry Andric const MCExpr *Expr = Sym.getVariableValue(); 8210b57cec5SDimitry Andric const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); 8220b57cec5SDimitry Andric if (Inner) { 8230b57cec5SDimitry Andric if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) 8240b57cec5SDimitry Andric return false; 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric if (InSet) 8280b57cec5SDimitry Andric return true; 8290b57cec5SDimitry Andric return !Sym.isInSection(); 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 8330b57cec5SDimitry Andric const MCAsmLayout *Layout, 8340b57cec5SDimitry Andric const MCFixup *Fixup, 8350b57cec5SDimitry Andric const SectionAddrMap *Addrs, 8360b57cec5SDimitry Andric bool InSet) const { 8370b57cec5SDimitry Andric ++stats::MCExprEvaluate; 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric switch (getKind()) { 8400b57cec5SDimitry Andric case Target: 8410b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, 8420b57cec5SDimitry Andric Fixup); 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric case Constant: 8450b57cec5SDimitry Andric Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 8460b57cec5SDimitry Andric return true; 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric case SymbolRef: { 8490b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 8500b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 851e8d8bef9SDimitry Andric const auto Kind = SRE->getKind(); 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric // Evaluate recursively if this is a variable. 854e8d8bef9SDimitry Andric if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && 8550b57cec5SDimitry Andric canExpand(Sym, InSet)) { 8560b57cec5SDimitry Andric bool IsMachO = SRE->hasSubsectionsViaSymbols(); 8570b57cec5SDimitry Andric if (Sym.getVariableValue()->evaluateAsRelocatableImpl( 8580b57cec5SDimitry Andric Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { 859e8d8bef9SDimitry Andric if (Kind != MCSymbolRefExpr::VK_None) { 860e8d8bef9SDimitry Andric if (Res.isAbsolute()) { 861e8d8bef9SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 862e8d8bef9SDimitry Andric return true; 863e8d8bef9SDimitry Andric } 864e8d8bef9SDimitry Andric // If the reference has a variant kind, we can only handle expressions 865e8d8bef9SDimitry Andric // which evaluate exactly to a single unadorned symbol. Attach the 866e8d8bef9SDimitry Andric // original VariantKind to SymA of the result. 867e8d8bef9SDimitry Andric if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || 868e8d8bef9SDimitry Andric Res.getSymB() || Res.getConstant()) 869e8d8bef9SDimitry Andric return false; 870e8d8bef9SDimitry Andric Res = 871e8d8bef9SDimitry Andric MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), 872e8d8bef9SDimitry Andric Kind, Asm->getContext()), 873e8d8bef9SDimitry Andric Res.getSymB(), Res.getConstant(), Res.getRefKind()); 874e8d8bef9SDimitry Andric } 8750b57cec5SDimitry Andric if (!IsMachO) 8760b57cec5SDimitry Andric return true; 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric const MCSymbolRefExpr *A = Res.getSymA(); 8790b57cec5SDimitry Andric const MCSymbolRefExpr *B = Res.getSymB(); 8800b57cec5SDimitry Andric // FIXME: This is small hack. Given 8810b57cec5SDimitry Andric // a = b + 4 8820b57cec5SDimitry Andric // .long a 8830b57cec5SDimitry Andric // the OS X assembler will completely drop the 4. We should probably 8840b57cec5SDimitry Andric // include it in the relocation or produce an error if that is not 8850b57cec5SDimitry Andric // possible. 8860b57cec5SDimitry Andric // Allow constant expressions. 8870b57cec5SDimitry Andric if (!A && !B) 8880b57cec5SDimitry Andric return true; 8890b57cec5SDimitry Andric // Allows aliases with zero offset. 8900b57cec5SDimitry Andric if (Res.getConstant() == 0 && (!A || !B)) 8910b57cec5SDimitry Andric return true; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 8960b57cec5SDimitry Andric return true; 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric case Unary: { 9000b57cec5SDimitry Andric const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 9010b57cec5SDimitry Andric MCValue Value; 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, 9040b57cec5SDimitry Andric Addrs, InSet)) 9050b57cec5SDimitry Andric return false; 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric switch (AUE->getOpcode()) { 9080b57cec5SDimitry Andric case MCUnaryExpr::LNot: 9090b57cec5SDimitry Andric if (!Value.isAbsolute()) 9100b57cec5SDimitry Andric return false; 9110b57cec5SDimitry Andric Res = MCValue::get(!Value.getConstant()); 9120b57cec5SDimitry Andric break; 9130b57cec5SDimitry Andric case MCUnaryExpr::Minus: 9140b57cec5SDimitry Andric /// -(a - b + const) ==> (b - a - const) 9150b57cec5SDimitry Andric if (Value.getSymA() && !Value.getSymB()) 9160b57cec5SDimitry Andric return false; 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 9190b57cec5SDimitry Andric Res = MCValue::get(Value.getSymB(), Value.getSymA(), 9200b57cec5SDimitry Andric -(uint64_t)Value.getConstant()); 9210b57cec5SDimitry Andric break; 9220b57cec5SDimitry Andric case MCUnaryExpr::Not: 9230b57cec5SDimitry Andric if (!Value.isAbsolute()) 9240b57cec5SDimitry Andric return false; 9250b57cec5SDimitry Andric Res = MCValue::get(~Value.getConstant()); 9260b57cec5SDimitry Andric break; 9270b57cec5SDimitry Andric case MCUnaryExpr::Plus: 9280b57cec5SDimitry Andric Res = Value; 9290b57cec5SDimitry Andric break; 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric return true; 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric case Binary: { 9360b57cec5SDimitry Andric const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 9370b57cec5SDimitry Andric MCValue LHSValue, RHSValue; 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, 9400b57cec5SDimitry Andric Addrs, InSet) || 9410b57cec5SDimitry Andric !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, 9420b57cec5SDimitry Andric Addrs, InSet)) { 9430b57cec5SDimitry Andric // Check if both are Target Expressions, see if we can compare them. 94406c3fb27SDimitry Andric if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) { 94506c3fb27SDimitry Andric const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS()); 9460b57cec5SDimitry Andric switch (ABE->getOpcode()) { 9470b57cec5SDimitry Andric case MCBinaryExpr::EQ: 94806c3fb27SDimitry Andric Res = MCValue::get(L->isEqualTo(R) ? -1 : 0); 9490b57cec5SDimitry Andric return true; 9500b57cec5SDimitry Andric case MCBinaryExpr::NE: 95106c3fb27SDimitry Andric Res = MCValue::get(L->isEqualTo(R) ? 0 : -1); 9520b57cec5SDimitry Andric return true; 95306c3fb27SDimitry Andric default: 95406c3fb27SDimitry Andric break; 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric return false; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric // We only support a few operations on non-constant expressions, handle 9610b57cec5SDimitry Andric // those first. 9620b57cec5SDimitry Andric if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 9630b57cec5SDimitry Andric switch (ABE->getOpcode()) { 9640b57cec5SDimitry Andric default: 9650b57cec5SDimitry Andric return false; 9660b57cec5SDimitry Andric case MCBinaryExpr::Sub: 9670b57cec5SDimitry Andric // Negate RHS and add. 9680b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 969*5f757f3fSDimitry Andric return EvaluateSymbolicAdd( 970*5f757f3fSDimitry Andric Asm, Layout, Addrs, InSet, LHSValue, 971*5f757f3fSDimitry Andric MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(), 972*5f757f3fSDimitry Andric -(uint64_t)RHSValue.getConstant(), 973*5f757f3fSDimitry Andric RHSValue.getRefKind()), 974*5f757f3fSDimitry Andric Res); 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric case MCBinaryExpr::Add: 977*5f757f3fSDimitry Andric return EvaluateSymbolicAdd( 978*5f757f3fSDimitry Andric Asm, Layout, Addrs, InSet, LHSValue, 979*5f757f3fSDimitry Andric MCValue::get(RHSValue.getSymA(), RHSValue.getSymB(), 980*5f757f3fSDimitry Andric RHSValue.getConstant(), RHSValue.getRefKind()), 981*5f757f3fSDimitry Andric Res); 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric // FIXME: We need target hooks for the evaluation. It may be limited in 9860b57cec5SDimitry Andric // width, and gas defines the result of comparisons differently from 9870b57cec5SDimitry Andric // Apple as. 9880b57cec5SDimitry Andric int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 9890b57cec5SDimitry Andric int64_t Result = 0; 9900b57cec5SDimitry Andric auto Op = ABE->getOpcode(); 9910b57cec5SDimitry Andric switch (Op) { 9920b57cec5SDimitry Andric case MCBinaryExpr::AShr: Result = LHS >> RHS; break; 9930b57cec5SDimitry Andric case MCBinaryExpr::Add: Result = LHS + RHS; break; 9940b57cec5SDimitry Andric case MCBinaryExpr::And: Result = LHS & RHS; break; 9950b57cec5SDimitry Andric case MCBinaryExpr::Div: 9960b57cec5SDimitry Andric case MCBinaryExpr::Mod: 9970b57cec5SDimitry Andric // Handle division by zero. gas just emits a warning and keeps going, 9980b57cec5SDimitry Andric // we try to be stricter. 9990b57cec5SDimitry Andric // FIXME: Currently the caller of this function has no way to understand 10000b57cec5SDimitry Andric // we're bailing out because of 'division by zero'. Therefore, it will 10010b57cec5SDimitry Andric // emit a 'expected relocatable expression' error. It would be nice to 10020b57cec5SDimitry Andric // change this code to emit a better diagnostic. 10030b57cec5SDimitry Andric if (RHS == 0) 10040b57cec5SDimitry Andric return false; 10050b57cec5SDimitry Andric if (ABE->getOpcode() == MCBinaryExpr::Div) 10060b57cec5SDimitry Andric Result = LHS / RHS; 10070b57cec5SDimitry Andric else 10080b57cec5SDimitry Andric Result = LHS % RHS; 10090b57cec5SDimitry Andric break; 10100b57cec5SDimitry Andric case MCBinaryExpr::EQ: Result = LHS == RHS; break; 10110b57cec5SDimitry Andric case MCBinaryExpr::GT: Result = LHS > RHS; break; 10120b57cec5SDimitry Andric case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 10130b57cec5SDimitry Andric case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 10140b57cec5SDimitry Andric case MCBinaryExpr::LOr: Result = LHS || RHS; break; 10150b57cec5SDimitry Andric case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; 10160b57cec5SDimitry Andric case MCBinaryExpr::LT: Result = LHS < RHS; break; 10170b57cec5SDimitry Andric case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 10180b57cec5SDimitry Andric case MCBinaryExpr::Mul: Result = LHS * RHS; break; 10190b57cec5SDimitry Andric case MCBinaryExpr::NE: Result = LHS != RHS; break; 10200b57cec5SDimitry Andric case MCBinaryExpr::Or: Result = LHS | RHS; break; 1021e8d8bef9SDimitry Andric case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; 10220b57cec5SDimitry Andric case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; 10230b57cec5SDimitry Andric case MCBinaryExpr::Sub: Result = LHS - RHS; break; 10240b57cec5SDimitry Andric case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 10250b57cec5SDimitry Andric } 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric switch (Op) { 10280b57cec5SDimitry Andric default: 10290b57cec5SDimitry Andric Res = MCValue::get(Result); 10300b57cec5SDimitry Andric break; 10310b57cec5SDimitry Andric case MCBinaryExpr::EQ: 10320b57cec5SDimitry Andric case MCBinaryExpr::GT: 10330b57cec5SDimitry Andric case MCBinaryExpr::GTE: 10340b57cec5SDimitry Andric case MCBinaryExpr::LT: 10350b57cec5SDimitry Andric case MCBinaryExpr::LTE: 10360b57cec5SDimitry Andric case MCBinaryExpr::NE: 10370b57cec5SDimitry Andric // A comparison operator returns a -1 if true and 0 if false. 10380b57cec5SDimitry Andric Res = MCValue::get(Result ? -1 : 0); 10390b57cec5SDimitry Andric break; 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric return true; 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric 10490b57cec5SDimitry Andric MCFragment *MCExpr::findAssociatedFragment() const { 10500b57cec5SDimitry Andric switch (getKind()) { 10510b57cec5SDimitry Andric case Target: 10520b57cec5SDimitry Andric // We never look through target specific expressions. 10530b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->findAssociatedFragment(); 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric case Constant: 10560b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric case SymbolRef: { 10590b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 10600b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 10610b57cec5SDimitry Andric return Sym.getFragment(); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric case Unary: 10650b57cec5SDimitry Andric return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); 10660b57cec5SDimitry Andric 10670b57cec5SDimitry Andric case Binary: { 10680b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 10690b57cec5SDimitry Andric MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); 10700b57cec5SDimitry Andric MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric // If either is absolute, return the other. 10730b57cec5SDimitry Andric if (LHS_F == MCSymbol::AbsolutePseudoFragment) 10740b57cec5SDimitry Andric return RHS_F; 10750b57cec5SDimitry Andric if (RHS_F == MCSymbol::AbsolutePseudoFragment) 10760b57cec5SDimitry Andric return LHS_F; 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric // Not always correct, but probably the best we can do without more context. 10790b57cec5SDimitry Andric if (BE->getOpcode() == MCBinaryExpr::Sub) 10800b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric // Otherwise, return the first non-null fragment. 10830b57cec5SDimitry Andric return LHS_F ? LHS_F : RHS_F; 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 10880b57cec5SDimitry Andric } 1089