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. 78*81ad6265SDimitry Andric bool UseParens = MAI && MAI->useParensForDollarSignNames() && !InParens && 79*81ad6265SDimitry Andric !Sym.getName().empty() && Sym.getName()[0] == '$'; 80*81ad6265SDimitry 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"; 3300b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD: return "got@tlsld"; 3310b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 3320b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; 3330b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 3345ffd83dbSDimitry Andric case VK_PPC_GOT_PCREL: 3355ffd83dbSDimitry Andric return "got@pcrel"; 336e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSGD_PCREL: 337e8d8bef9SDimitry Andric return "got@tlsgd@pcrel"; 338e8d8bef9SDimitry Andric case VK_PPC_GOT_TLSLD_PCREL: 339e8d8bef9SDimitry Andric return "got@tlsld@pcrel"; 340e8d8bef9SDimitry Andric case VK_PPC_GOT_TPREL_PCREL: 341e8d8bef9SDimitry Andric return "got@tprel@pcrel"; 342e8d8bef9SDimitry Andric case VK_PPC_TLS_PCREL: 343e8d8bef9SDimitry Andric return "tls@pcrel"; 3440b57cec5SDimitry Andric case VK_PPC_TLSLD: return "tlsld"; 3450b57cec5SDimitry Andric case VK_PPC_LOCAL: return "local"; 3465ffd83dbSDimitry Andric case VK_PPC_NOTOC: return "notoc"; 347e8d8bef9SDimitry Andric case VK_PPC_PCREL_OPT: return "<<invalid>>"; 3480b57cec5SDimitry Andric case VK_COFF_IMGREL32: return "IMGREL"; 3490b57cec5SDimitry Andric case VK_Hexagon_LO16: return "LO16"; 3500b57cec5SDimitry Andric case VK_Hexagon_HI16: return "HI16"; 3510b57cec5SDimitry Andric case VK_Hexagon_GPREL: return "GPREL"; 3520b57cec5SDimitry Andric case VK_Hexagon_GD_GOT: return "GDGOT"; 3530b57cec5SDimitry Andric case VK_Hexagon_LD_GOT: return "LDGOT"; 3540b57cec5SDimitry Andric case VK_Hexagon_GD_PLT: return "GDPLT"; 3550b57cec5SDimitry Andric case VK_Hexagon_LD_PLT: return "LDPLT"; 3560b57cec5SDimitry Andric case VK_Hexagon_IE: return "IE"; 3570b57cec5SDimitry Andric case VK_Hexagon_IE_GOT: return "IEGOT"; 3580b57cec5SDimitry Andric case VK_WASM_TYPEINDEX: return "TYPEINDEX"; 3590b57cec5SDimitry Andric case VK_WASM_MBREL: return "MBREL"; 360e8d8bef9SDimitry Andric case VK_WASM_TLSREL: return "TLSREL"; 3610b57cec5SDimitry Andric case VK_WASM_TBREL: return "TBREL"; 362349cc55cSDimitry Andric case VK_WASM_GOT_TLS: return "GOT@TLS"; 3630b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; 3640b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; 3650b57cec5SDimitry Andric case VK_AMDGPU_REL32_LO: return "rel32@lo"; 3660b57cec5SDimitry Andric case VK_AMDGPU_REL32_HI: return "rel32@hi"; 3670b57cec5SDimitry Andric case VK_AMDGPU_REL64: return "rel64"; 3680b57cec5SDimitry Andric case VK_AMDGPU_ABS32_LO: return "abs32@lo"; 3690b57cec5SDimitry Andric case VK_AMDGPU_ABS32_HI: return "abs32@hi"; 3705ffd83dbSDimitry Andric case VK_VE_HI32: return "hi"; 3715ffd83dbSDimitry Andric case VK_VE_LO32: return "lo"; 3725ffd83dbSDimitry Andric case VK_VE_PC_HI32: return "pc_hi"; 3735ffd83dbSDimitry Andric case VK_VE_PC_LO32: return "pc_lo"; 3745ffd83dbSDimitry Andric case VK_VE_GOT_HI32: return "got_hi"; 3755ffd83dbSDimitry Andric case VK_VE_GOT_LO32: return "got_lo"; 3765ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: return "gotoff_hi"; 3775ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: return "gotoff_lo"; 3785ffd83dbSDimitry Andric case VK_VE_PLT_HI32: return "plt_hi"; 3795ffd83dbSDimitry Andric case VK_VE_PLT_LO32: return "plt_lo"; 3805ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: return "tls_gd_hi"; 3815ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: return "tls_gd_lo"; 3825ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: return "tpoff_hi"; 3835ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: return "tpoff_lo"; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric llvm_unreachable("Invalid variant kind"); 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind 3890b57cec5SDimitry Andric MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 3900b57cec5SDimitry Andric return StringSwitch<VariantKind>(Name.lower()) 3910b57cec5SDimitry Andric .Case("dtprel", VK_DTPREL) 3920b57cec5SDimitry Andric .Case("dtpoff", VK_DTPOFF) 3930b57cec5SDimitry Andric .Case("got", VK_GOT) 3940b57cec5SDimitry Andric .Case("gotoff", VK_GOTOFF) 3950b57cec5SDimitry Andric .Case("gotrel", VK_GOTREL) 3965ffd83dbSDimitry Andric .Case("pcrel", VK_PCREL) 3970b57cec5SDimitry Andric .Case("gotpcrel", VK_GOTPCREL) 398349cc55cSDimitry Andric .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX) 3990b57cec5SDimitry Andric .Case("gottpoff", VK_GOTTPOFF) 4000b57cec5SDimitry Andric .Case("indntpoff", VK_INDNTPOFF) 4010b57cec5SDimitry Andric .Case("ntpoff", VK_NTPOFF) 4020b57cec5SDimitry Andric .Case("gotntpoff", VK_GOTNTPOFF) 4030b57cec5SDimitry Andric .Case("plt", VK_PLT) 4040b57cec5SDimitry Andric .Case("tlscall", VK_TLSCALL) 4050b57cec5SDimitry Andric .Case("tlsdesc", VK_TLSDESC) 4060b57cec5SDimitry Andric .Case("tlsgd", VK_TLSGD) 4070b57cec5SDimitry Andric .Case("tlsld", VK_TLSLD) 4080b57cec5SDimitry Andric .Case("tlsldm", VK_TLSLDM) 4090b57cec5SDimitry Andric .Case("tpoff", VK_TPOFF) 4100b57cec5SDimitry Andric .Case("tprel", VK_TPREL) 4110b57cec5SDimitry Andric .Case("tlvp", VK_TLVP) 4120b57cec5SDimitry Andric .Case("tlvppage", VK_TLVPPAGE) 4130b57cec5SDimitry Andric .Case("tlvppageoff", VK_TLVPPAGEOFF) 4140b57cec5SDimitry Andric .Case("page", VK_PAGE) 4150b57cec5SDimitry Andric .Case("pageoff", VK_PAGEOFF) 4160b57cec5SDimitry Andric .Case("gotpage", VK_GOTPAGE) 4170b57cec5SDimitry Andric .Case("gotpageoff", VK_GOTPAGEOFF) 4180b57cec5SDimitry Andric .Case("imgrel", VK_COFF_IMGREL32) 4190b57cec5SDimitry Andric .Case("secrel32", VK_SECREL) 4200b57cec5SDimitry Andric .Case("size", VK_SIZE) 4210b57cec5SDimitry Andric .Case("abs8", VK_X86_ABS8) 422e8d8bef9SDimitry Andric .Case("pltoff", VK_X86_PLTOFF) 4230b57cec5SDimitry Andric .Case("l", VK_PPC_LO) 4240b57cec5SDimitry Andric .Case("h", VK_PPC_HI) 4250b57cec5SDimitry Andric .Case("ha", VK_PPC_HA) 4260b57cec5SDimitry Andric .Case("high", VK_PPC_HIGH) 4270b57cec5SDimitry Andric .Case("higha", VK_PPC_HIGHA) 4280b57cec5SDimitry Andric .Case("higher", VK_PPC_HIGHER) 4290b57cec5SDimitry Andric .Case("highera", VK_PPC_HIGHERA) 4300b57cec5SDimitry Andric .Case("highest", VK_PPC_HIGHEST) 4310b57cec5SDimitry Andric .Case("highesta", VK_PPC_HIGHESTA) 4320b57cec5SDimitry Andric .Case("got@l", VK_PPC_GOT_LO) 4330b57cec5SDimitry Andric .Case("got@h", VK_PPC_GOT_HI) 4340b57cec5SDimitry Andric .Case("got@ha", VK_PPC_GOT_HA) 4350b57cec5SDimitry Andric .Case("local", VK_PPC_LOCAL) 4360b57cec5SDimitry Andric .Case("tocbase", VK_PPC_TOCBASE) 4370b57cec5SDimitry Andric .Case("toc", VK_PPC_TOC) 4380b57cec5SDimitry Andric .Case("toc@l", VK_PPC_TOC_LO) 4390b57cec5SDimitry Andric .Case("toc@h", VK_PPC_TOC_HI) 4400b57cec5SDimitry Andric .Case("toc@ha", VK_PPC_TOC_HA) 4418bcb0991SDimitry Andric .Case("u", VK_PPC_U) 4428bcb0991SDimitry Andric .Case("l", VK_PPC_L) 4430b57cec5SDimitry Andric .Case("tls", VK_PPC_TLS) 4440b57cec5SDimitry Andric .Case("dtpmod", VK_PPC_DTPMOD) 4450b57cec5SDimitry Andric .Case("tprel@l", VK_PPC_TPREL_LO) 4460b57cec5SDimitry Andric .Case("tprel@h", VK_PPC_TPREL_HI) 4470b57cec5SDimitry Andric .Case("tprel@ha", VK_PPC_TPREL_HA) 4480b57cec5SDimitry Andric .Case("tprel@high", VK_PPC_TPREL_HIGH) 4490b57cec5SDimitry Andric .Case("tprel@higha", VK_PPC_TPREL_HIGHA) 4500b57cec5SDimitry Andric .Case("tprel@higher", VK_PPC_TPREL_HIGHER) 4510b57cec5SDimitry Andric .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) 4520b57cec5SDimitry Andric .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) 4530b57cec5SDimitry Andric .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) 4540b57cec5SDimitry Andric .Case("dtprel@l", VK_PPC_DTPREL_LO) 4550b57cec5SDimitry Andric .Case("dtprel@h", VK_PPC_DTPREL_HI) 4560b57cec5SDimitry Andric .Case("dtprel@ha", VK_PPC_DTPREL_HA) 4570b57cec5SDimitry Andric .Case("dtprel@high", VK_PPC_DTPREL_HIGH) 4580b57cec5SDimitry Andric .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) 4590b57cec5SDimitry Andric .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) 4600b57cec5SDimitry Andric .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) 4610b57cec5SDimitry Andric .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) 4620b57cec5SDimitry Andric .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) 4630b57cec5SDimitry Andric .Case("got@tprel", VK_PPC_GOT_TPREL) 4640b57cec5SDimitry Andric .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 4650b57cec5SDimitry Andric .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) 4660b57cec5SDimitry Andric .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 4670b57cec5SDimitry Andric .Case("got@dtprel", VK_PPC_GOT_DTPREL) 4680b57cec5SDimitry Andric .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) 4690b57cec5SDimitry Andric .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) 4700b57cec5SDimitry Andric .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) 4710b57cec5SDimitry Andric .Case("got@tlsgd", VK_PPC_GOT_TLSGD) 4720b57cec5SDimitry Andric .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 4730b57cec5SDimitry Andric .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) 4740b57cec5SDimitry Andric .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 4750b57cec5SDimitry Andric .Case("got@tlsld", VK_PPC_GOT_TLSLD) 4760b57cec5SDimitry Andric .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 4770b57cec5SDimitry Andric .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) 4780b57cec5SDimitry Andric .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 4795ffd83dbSDimitry Andric .Case("got@pcrel", VK_PPC_GOT_PCREL) 480e8d8bef9SDimitry Andric .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) 481e8d8bef9SDimitry Andric .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) 482e8d8bef9SDimitry Andric .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) 483e8d8bef9SDimitry Andric .Case("tls@pcrel", VK_PPC_TLS_PCREL) 4845ffd83dbSDimitry Andric .Case("notoc", VK_PPC_NOTOC) 4850b57cec5SDimitry Andric .Case("gdgot", VK_Hexagon_GD_GOT) 4860b57cec5SDimitry Andric .Case("gdplt", VK_Hexagon_GD_PLT) 4870b57cec5SDimitry Andric .Case("iegot", VK_Hexagon_IE_GOT) 4880b57cec5SDimitry Andric .Case("ie", VK_Hexagon_IE) 4890b57cec5SDimitry Andric .Case("ldgot", VK_Hexagon_LD_GOT) 4900b57cec5SDimitry Andric .Case("ldplt", VK_Hexagon_LD_PLT) 4910b57cec5SDimitry Andric .Case("none", VK_ARM_NONE) 4920b57cec5SDimitry Andric .Case("got_prel", VK_ARM_GOT_PREL) 4930b57cec5SDimitry Andric .Case("target1", VK_ARM_TARGET1) 4940b57cec5SDimitry Andric .Case("target2", VK_ARM_TARGET2) 4950b57cec5SDimitry Andric .Case("prel31", VK_ARM_PREL31) 4960b57cec5SDimitry Andric .Case("sbrel", VK_ARM_SBREL) 4970b57cec5SDimitry Andric .Case("tlsldo", VK_ARM_TLSLDO) 4980b57cec5SDimitry Andric .Case("lo8", VK_AVR_LO8) 4990b57cec5SDimitry Andric .Case("hi8", VK_AVR_HI8) 5000b57cec5SDimitry Andric .Case("hlo8", VK_AVR_HLO8) 5010b57cec5SDimitry Andric .Case("typeindex", VK_WASM_TYPEINDEX) 5020b57cec5SDimitry Andric .Case("tbrel", VK_WASM_TBREL) 5030b57cec5SDimitry Andric .Case("mbrel", VK_WASM_MBREL) 504e8d8bef9SDimitry Andric .Case("tlsrel", VK_WASM_TLSREL) 505349cc55cSDimitry Andric .Case("got@tls", VK_WASM_GOT_TLS) 5060b57cec5SDimitry Andric .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) 5070b57cec5SDimitry Andric .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) 5080b57cec5SDimitry Andric .Case("rel32@lo", VK_AMDGPU_REL32_LO) 5090b57cec5SDimitry Andric .Case("rel32@hi", VK_AMDGPU_REL32_HI) 5100b57cec5SDimitry Andric .Case("rel64", VK_AMDGPU_REL64) 5110b57cec5SDimitry Andric .Case("abs32@lo", VK_AMDGPU_ABS32_LO) 5120b57cec5SDimitry Andric .Case("abs32@hi", VK_AMDGPU_ABS32_HI) 5135ffd83dbSDimitry Andric .Case("hi", VK_VE_HI32) 5145ffd83dbSDimitry Andric .Case("lo", VK_VE_LO32) 5155ffd83dbSDimitry Andric .Case("pc_hi", VK_VE_PC_HI32) 5165ffd83dbSDimitry Andric .Case("pc_lo", VK_VE_PC_LO32) 5175ffd83dbSDimitry Andric .Case("got_hi", VK_VE_GOT_HI32) 5185ffd83dbSDimitry Andric .Case("got_lo", VK_VE_GOT_LO32) 5195ffd83dbSDimitry Andric .Case("gotoff_hi", VK_VE_GOTOFF_HI32) 5205ffd83dbSDimitry Andric .Case("gotoff_lo", VK_VE_GOTOFF_LO32) 5215ffd83dbSDimitry Andric .Case("plt_hi", VK_VE_PLT_HI32) 5225ffd83dbSDimitry Andric .Case("plt_lo", VK_VE_PLT_LO32) 5235ffd83dbSDimitry Andric .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) 5245ffd83dbSDimitry Andric .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) 5255ffd83dbSDimitry Andric .Case("tpoff_hi", VK_VE_TPOFF_HI32) 5265ffd83dbSDimitry Andric .Case("tpoff_lo", VK_VE_TPOFF_LO32) 5270b57cec5SDimitry Andric .Default(VK_Invalid); 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric /* *** */ 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric void MCTargetExpr::anchor() {} 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric /* *** */ 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { 5378bcb0991SDimitry Andric return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5410b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5428bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 5460b57cec5SDimitry Andric const MCAsmLayout &Layout, 5470b57cec5SDimitry Andric const SectionAddrMap &Addrs) const { 5488bcb0991SDimitry Andric // Setting InSet causes us to absolutize differences across sections and that 5498bcb0991SDimitry Andric // is what the MachO writer uses Addrs for. 5508bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 5548bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); 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::evaluateKnownAbsolute(int64_t &Res, 5620b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 5630b57cec5SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, 5640b57cec5SDimitry Andric true); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 5680b57cec5SDimitry Andric const MCAsmLayout *Layout, 5690b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet) const { 5700b57cec5SDimitry Andric MCValue Value; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric // Fast path constants. 5730b57cec5SDimitry Andric if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 5740b57cec5SDimitry Andric Res = CE->getValue(); 5750b57cec5SDimitry Andric return true; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric bool IsRelocatable = 5790b57cec5SDimitry Andric evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric // Record the current value. 5820b57cec5SDimitry Andric Res = Value.getConstant(); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric return IsRelocatable && Value.isAbsolute(); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric /// Helper method for \see EvaluateSymbolAdd(). 5880b57cec5SDimitry Andric static void AttemptToFoldSymbolOffsetDifference( 5890b57cec5SDimitry Andric const MCAssembler *Asm, const MCAsmLayout *Layout, 5900b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, 5910b57cec5SDimitry Andric const MCSymbolRefExpr *&B, int64_t &Addend) { 5920b57cec5SDimitry Andric if (!A || !B) 5930b57cec5SDimitry Andric return; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric const MCSymbol &SA = A->getSymbol(); 5960b57cec5SDimitry Andric const MCSymbol &SB = B->getSymbol(); 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric if (SA.isUndefined() || SB.isUndefined()) 5990b57cec5SDimitry Andric return; 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 6020b57cec5SDimitry Andric return; 6030b57cec5SDimitry Andric 604e8d8bef9SDimitry Andric auto FinalizeFolding = [&]() { 6050b57cec5SDimitry Andric // Pointers to Thumb symbols need to have their low-bit set to allow 6060b57cec5SDimitry Andric // for interworking. 6070b57cec5SDimitry Andric if (Asm->isThumbFunc(&SA)) 6080b57cec5SDimitry Andric Addend |= 1; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric // If symbol is labeled as micromips, we set low-bit to ensure 6110b57cec5SDimitry Andric // correct offset in .gcc_except_table 6120b57cec5SDimitry Andric if (Asm->getBackend().isMicroMips(&SA)) 6130b57cec5SDimitry Andric Addend |= 1; 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric // Clear the symbol expr pointers to indicate we have folded these 6160b57cec5SDimitry Andric // operands. 6170b57cec5SDimitry Andric A = B = nullptr; 618e8d8bef9SDimitry Andric }; 6190b57cec5SDimitry Andric 620e8d8bef9SDimitry Andric const MCFragment *FA = SA.getFragment(); 621e8d8bef9SDimitry Andric const MCFragment *FB = SB.getFragment(); 622e8d8bef9SDimitry Andric // If both symbols are in the same fragment, return the difference of their 623e8d8bef9SDimitry Andric // offsets 624e8d8bef9SDimitry Andric if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() && 625e8d8bef9SDimitry Andric !SB.isUnset()) { 626e8d8bef9SDimitry Andric Addend += SA.getOffset() - SB.getOffset(); 627e8d8bef9SDimitry Andric return FinalizeFolding(); 628e8d8bef9SDimitry Andric } 6290b57cec5SDimitry Andric 6305ffd83dbSDimitry Andric const MCSection &SecA = *FA->getParent(); 6315ffd83dbSDimitry Andric const MCSection &SecB = *FB->getParent(); 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric if ((&SecA != &SecB) && !Addrs) 6340b57cec5SDimitry Andric return; 6350b57cec5SDimitry Andric 636e8d8bef9SDimitry Andric if (Layout) { 6375ffd83dbSDimitry Andric // One of the symbol involved is part of a fragment being laid out. Quit now 6385ffd83dbSDimitry Andric // to avoid a self loop. 6395ffd83dbSDimitry Andric if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB)) 6405ffd83dbSDimitry Andric return; 6415ffd83dbSDimitry Andric 642e8d8bef9SDimitry Andric // Eagerly evaluate when layout is finalized. 6430b57cec5SDimitry Andric Addend += Layout->getSymbolOffset(A->getSymbol()) - 6440b57cec5SDimitry Andric Layout->getSymbolOffset(B->getSymbol()); 6450b57cec5SDimitry Andric if (Addrs && (&SecA != &SecB)) 6460b57cec5SDimitry Andric Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 6470b57cec5SDimitry Andric 648e8d8bef9SDimitry Andric FinalizeFolding(); 649e8d8bef9SDimitry Andric } else { 650e8d8bef9SDimitry Andric // When layout is not finalized, our ability to resolve differences between 651e8d8bef9SDimitry Andric // symbols is limited to specific cases where the fragments between two 652e8d8bef9SDimitry Andric // symbols (including the fragments the symbols are defined in) are 653e8d8bef9SDimitry Andric // fixed-size fragments so the difference can be calculated. For example, 654e8d8bef9SDimitry Andric // this is important when the Subtarget is changed and a new MCDataFragment 655e8d8bef9SDimitry Andric // is created in the case of foo: instr; .arch_extension ext; instr .if . - 656e8d8bef9SDimitry Andric // foo. 657e8d8bef9SDimitry Andric if (SA.isVariable() || SA.isUnset() || SB.isVariable() || SB.isUnset() || 658e8d8bef9SDimitry Andric FA->getKind() != MCFragment::FT_Data || 659e8d8bef9SDimitry Andric FB->getKind() != MCFragment::FT_Data || 660e8d8bef9SDimitry Andric FA->getSubsectionNumber() != FB->getSubsectionNumber()) 661e8d8bef9SDimitry Andric return; 662e8d8bef9SDimitry Andric // Try to find a constant displacement from FA to FB, add the displacement 663e8d8bef9SDimitry Andric // between the offset in FA of SA and the offset in FB of SB. 664e8d8bef9SDimitry Andric int64_t Displacement = SA.getOffset() - SB.getOffset(); 665e8d8bef9SDimitry Andric for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { 666e8d8bef9SDimitry Andric if (&*FI == FA) { 667e8d8bef9SDimitry Andric Addend += Displacement; 668e8d8bef9SDimitry Andric return FinalizeFolding(); 669e8d8bef9SDimitry Andric } 6700b57cec5SDimitry Andric 671e8d8bef9SDimitry Andric if (FI->getKind() != MCFragment::FT_Data) 672e8d8bef9SDimitry Andric return; 673e8d8bef9SDimitry Andric Displacement += cast<MCDataFragment>(FI)->getContents().size(); 674e8d8bef9SDimitry Andric } 675e8d8bef9SDimitry Andric } 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric /// Evaluate the result of an add between (conceptually) two MCValues. 6790b57cec5SDimitry Andric /// 6800b57cec5SDimitry Andric /// This routine conceptually attempts to construct an MCValue: 6810b57cec5SDimitry Andric /// Result = (Result_A - Result_B + Result_Cst) 6820b57cec5SDimitry Andric /// from two MCValue's LHS and RHS where 6830b57cec5SDimitry Andric /// Result = LHS + RHS 6840b57cec5SDimitry Andric /// and 6850b57cec5SDimitry Andric /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 6860b57cec5SDimitry Andric /// 687480093f4SDimitry Andric /// This routine attempts to aggressively fold the operands such that the result 6880b57cec5SDimitry Andric /// is representable in an MCValue, but may not always succeed. 6890b57cec5SDimitry Andric /// 6900b57cec5SDimitry Andric /// \returns True on success, false if the result is not representable in an 6910b57cec5SDimitry Andric /// MCValue. 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric /// NOTE: It is really important to have both the Asm and Layout arguments. 6940b57cec5SDimitry Andric /// They might look redundant, but this function can be used before layout 6950b57cec5SDimitry Andric /// is done (see the object streamer for example) and having the Asm argument 6960b57cec5SDimitry Andric /// lets us avoid relaxations early. 6970b57cec5SDimitry Andric static bool 6980b57cec5SDimitry Andric EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, 6990b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, 7000b57cec5SDimitry Andric const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, 7010b57cec5SDimitry Andric int64_t RHS_Cst, MCValue &Res) { 7020b57cec5SDimitry Andric // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 7030b57cec5SDimitry Andric // about dealing with modifiers. This will ultimately bite us, one day. 7040b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 7050b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 7060b57cec5SDimitry Andric int64_t LHS_Cst = LHS.getConstant(); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric // Fold the result constant immediately. 7090b57cec5SDimitry Andric int64_t Result_Cst = LHS_Cst + RHS_Cst; 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric assert((!Layout || Asm) && 7120b57cec5SDimitry Andric "Must have an assembler object if layout is given!"); 7130b57cec5SDimitry Andric 714fe6060f1SDimitry Andric // If we have a layout, we can fold resolved differences. 715fe6060f1SDimitry Andric if (Asm) { 7160b57cec5SDimitry Andric // First, fold out any differences which are fully resolved. By 7170b57cec5SDimitry Andric // reassociating terms in 7180b57cec5SDimitry Andric // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 7190b57cec5SDimitry Andric // we have the four possible differences: 7200b57cec5SDimitry Andric // (LHS_A - LHS_B), 7210b57cec5SDimitry Andric // (LHS_A - RHS_B), 7220b57cec5SDimitry Andric // (RHS_A - LHS_B), 7230b57cec5SDimitry Andric // (RHS_A - RHS_B). 7240b57cec5SDimitry Andric // Since we are attempting to be as aggressive as possible about folding, we 7250b57cec5SDimitry Andric // attempt to evaluate each possible alternative. 7260b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 7270b57cec5SDimitry Andric Result_Cst); 7280b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 7290b57cec5SDimitry Andric Result_Cst); 7300b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 7310b57cec5SDimitry Andric Result_Cst); 7320b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 7330b57cec5SDimitry Andric Result_Cst); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric // We can't represent the addition or subtraction of two symbols. 7370b57cec5SDimitry Andric if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 7380b57cec5SDimitry Andric return false; 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric // At this point, we have at most one additive symbol and one subtractive 7410b57cec5SDimitry Andric // symbol -- find them. 7420b57cec5SDimitry Andric const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 7430b57cec5SDimitry Andric const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric Res = MCValue::get(A, B, Result_Cst); 7460b57cec5SDimitry Andric return true; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatable(MCValue &Res, 7500b57cec5SDimitry Andric const MCAsmLayout *Layout, 7510b57cec5SDimitry Andric const MCFixup *Fixup) const { 7520b57cec5SDimitry Andric MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; 7530b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, 7540b57cec5SDimitry Andric false); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { 7580b57cec5SDimitry Andric MCAssembler *Assembler = &Layout.getAssembler(); 7590b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, 7600b57cec5SDimitry Andric true); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric static bool canExpand(const MCSymbol &Sym, bool InSet) { 7640b57cec5SDimitry Andric const MCExpr *Expr = Sym.getVariableValue(); 7650b57cec5SDimitry Andric const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); 7660b57cec5SDimitry Andric if (Inner) { 7670b57cec5SDimitry Andric if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) 7680b57cec5SDimitry Andric return false; 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric if (InSet) 7720b57cec5SDimitry Andric return true; 7730b57cec5SDimitry Andric return !Sym.isInSection(); 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 7770b57cec5SDimitry Andric const MCAsmLayout *Layout, 7780b57cec5SDimitry Andric const MCFixup *Fixup, 7790b57cec5SDimitry Andric const SectionAddrMap *Addrs, 7800b57cec5SDimitry Andric bool InSet) const { 7810b57cec5SDimitry Andric ++stats::MCExprEvaluate; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric switch (getKind()) { 7840b57cec5SDimitry Andric case Target: 7850b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, 7860b57cec5SDimitry Andric Fixup); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric case Constant: 7890b57cec5SDimitry Andric Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 7900b57cec5SDimitry Andric return true; 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric case SymbolRef: { 7930b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 7940b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 795e8d8bef9SDimitry Andric const auto Kind = SRE->getKind(); 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric // Evaluate recursively if this is a variable. 798e8d8bef9SDimitry Andric if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && 7990b57cec5SDimitry Andric canExpand(Sym, InSet)) { 8000b57cec5SDimitry Andric bool IsMachO = SRE->hasSubsectionsViaSymbols(); 8010b57cec5SDimitry Andric if (Sym.getVariableValue()->evaluateAsRelocatableImpl( 8020b57cec5SDimitry Andric Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { 803e8d8bef9SDimitry Andric if (Kind != MCSymbolRefExpr::VK_None) { 804e8d8bef9SDimitry Andric if (Res.isAbsolute()) { 805e8d8bef9SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 806e8d8bef9SDimitry Andric return true; 807e8d8bef9SDimitry Andric } 808e8d8bef9SDimitry Andric // If the reference has a variant kind, we can only handle expressions 809e8d8bef9SDimitry Andric // which evaluate exactly to a single unadorned symbol. Attach the 810e8d8bef9SDimitry Andric // original VariantKind to SymA of the result. 811e8d8bef9SDimitry Andric if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || 812e8d8bef9SDimitry Andric Res.getSymB() || Res.getConstant()) 813e8d8bef9SDimitry Andric return false; 814e8d8bef9SDimitry Andric Res = 815e8d8bef9SDimitry Andric MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), 816e8d8bef9SDimitry Andric Kind, Asm->getContext()), 817e8d8bef9SDimitry Andric Res.getSymB(), Res.getConstant(), Res.getRefKind()); 818e8d8bef9SDimitry Andric } 8190b57cec5SDimitry Andric if (!IsMachO) 8200b57cec5SDimitry Andric return true; 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric const MCSymbolRefExpr *A = Res.getSymA(); 8230b57cec5SDimitry Andric const MCSymbolRefExpr *B = Res.getSymB(); 8240b57cec5SDimitry Andric // FIXME: This is small hack. Given 8250b57cec5SDimitry Andric // a = b + 4 8260b57cec5SDimitry Andric // .long a 8270b57cec5SDimitry Andric // the OS X assembler will completely drop the 4. We should probably 8280b57cec5SDimitry Andric // include it in the relocation or produce an error if that is not 8290b57cec5SDimitry Andric // possible. 8300b57cec5SDimitry Andric // Allow constant expressions. 8310b57cec5SDimitry Andric if (!A && !B) 8320b57cec5SDimitry Andric return true; 8330b57cec5SDimitry Andric // Allows aliases with zero offset. 8340b57cec5SDimitry Andric if (Res.getConstant() == 0 && (!A || !B)) 8350b57cec5SDimitry Andric return true; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 8400b57cec5SDimitry Andric return true; 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric case Unary: { 8440b57cec5SDimitry Andric const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 8450b57cec5SDimitry Andric MCValue Value; 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, 8480b57cec5SDimitry Andric Addrs, InSet)) 8490b57cec5SDimitry Andric return false; 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric switch (AUE->getOpcode()) { 8520b57cec5SDimitry Andric case MCUnaryExpr::LNot: 8530b57cec5SDimitry Andric if (!Value.isAbsolute()) 8540b57cec5SDimitry Andric return false; 8550b57cec5SDimitry Andric Res = MCValue::get(!Value.getConstant()); 8560b57cec5SDimitry Andric break; 8570b57cec5SDimitry Andric case MCUnaryExpr::Minus: 8580b57cec5SDimitry Andric /// -(a - b + const) ==> (b - a - const) 8590b57cec5SDimitry Andric if (Value.getSymA() && !Value.getSymB()) 8600b57cec5SDimitry Andric return false; 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 8630b57cec5SDimitry Andric Res = MCValue::get(Value.getSymB(), Value.getSymA(), 8640b57cec5SDimitry Andric -(uint64_t)Value.getConstant()); 8650b57cec5SDimitry Andric break; 8660b57cec5SDimitry Andric case MCUnaryExpr::Not: 8670b57cec5SDimitry Andric if (!Value.isAbsolute()) 8680b57cec5SDimitry Andric return false; 8690b57cec5SDimitry Andric Res = MCValue::get(~Value.getConstant()); 8700b57cec5SDimitry Andric break; 8710b57cec5SDimitry Andric case MCUnaryExpr::Plus: 8720b57cec5SDimitry Andric Res = Value; 8730b57cec5SDimitry Andric break; 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric return true; 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric case Binary: { 8800b57cec5SDimitry Andric const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 8810b57cec5SDimitry Andric MCValue LHSValue, RHSValue; 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, 8840b57cec5SDimitry Andric Addrs, InSet) || 8850b57cec5SDimitry Andric !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, 8860b57cec5SDimitry Andric Addrs, InSet)) { 8870b57cec5SDimitry Andric // Check if both are Target Expressions, see if we can compare them. 8880b57cec5SDimitry Andric if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) 8890b57cec5SDimitry Andric if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) { 8900b57cec5SDimitry Andric switch (ABE->getOpcode()) { 8910b57cec5SDimitry Andric case MCBinaryExpr::EQ: 8920b57cec5SDimitry Andric Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0); 8930b57cec5SDimitry Andric return true; 8940b57cec5SDimitry Andric case MCBinaryExpr::NE: 8950b57cec5SDimitry Andric Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1); 8960b57cec5SDimitry Andric return true; 8970b57cec5SDimitry Andric default: break; 8980b57cec5SDimitry Andric } 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric return false; 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric // We only support a few operations on non-constant expressions, handle 9040b57cec5SDimitry Andric // those first. 9050b57cec5SDimitry Andric if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 9060b57cec5SDimitry Andric switch (ABE->getOpcode()) { 9070b57cec5SDimitry Andric default: 9080b57cec5SDimitry Andric return false; 9090b57cec5SDimitry Andric case MCBinaryExpr::Sub: 9100b57cec5SDimitry Andric // Negate RHS and add. 9110b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 9120b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 9130b57cec5SDimitry Andric RHSValue.getSymB(), RHSValue.getSymA(), 9140b57cec5SDimitry Andric -(uint64_t)RHSValue.getConstant(), Res); 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric case MCBinaryExpr::Add: 9170b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 9180b57cec5SDimitry Andric RHSValue.getSymA(), RHSValue.getSymB(), 9190b57cec5SDimitry Andric RHSValue.getConstant(), Res); 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric // FIXME: We need target hooks for the evaluation. It may be limited in 9240b57cec5SDimitry Andric // width, and gas defines the result of comparisons differently from 9250b57cec5SDimitry Andric // Apple as. 9260b57cec5SDimitry Andric int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 9270b57cec5SDimitry Andric int64_t Result = 0; 9280b57cec5SDimitry Andric auto Op = ABE->getOpcode(); 9290b57cec5SDimitry Andric switch (Op) { 9300b57cec5SDimitry Andric case MCBinaryExpr::AShr: Result = LHS >> RHS; break; 9310b57cec5SDimitry Andric case MCBinaryExpr::Add: Result = LHS + RHS; break; 9320b57cec5SDimitry Andric case MCBinaryExpr::And: Result = LHS & RHS; break; 9330b57cec5SDimitry Andric case MCBinaryExpr::Div: 9340b57cec5SDimitry Andric case MCBinaryExpr::Mod: 9350b57cec5SDimitry Andric // Handle division by zero. gas just emits a warning and keeps going, 9360b57cec5SDimitry Andric // we try to be stricter. 9370b57cec5SDimitry Andric // FIXME: Currently the caller of this function has no way to understand 9380b57cec5SDimitry Andric // we're bailing out because of 'division by zero'. Therefore, it will 9390b57cec5SDimitry Andric // emit a 'expected relocatable expression' error. It would be nice to 9400b57cec5SDimitry Andric // change this code to emit a better diagnostic. 9410b57cec5SDimitry Andric if (RHS == 0) 9420b57cec5SDimitry Andric return false; 9430b57cec5SDimitry Andric if (ABE->getOpcode() == MCBinaryExpr::Div) 9440b57cec5SDimitry Andric Result = LHS / RHS; 9450b57cec5SDimitry Andric else 9460b57cec5SDimitry Andric Result = LHS % RHS; 9470b57cec5SDimitry Andric break; 9480b57cec5SDimitry Andric case MCBinaryExpr::EQ: Result = LHS == RHS; break; 9490b57cec5SDimitry Andric case MCBinaryExpr::GT: Result = LHS > RHS; break; 9500b57cec5SDimitry Andric case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 9510b57cec5SDimitry Andric case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 9520b57cec5SDimitry Andric case MCBinaryExpr::LOr: Result = LHS || RHS; break; 9530b57cec5SDimitry Andric case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; 9540b57cec5SDimitry Andric case MCBinaryExpr::LT: Result = LHS < RHS; break; 9550b57cec5SDimitry Andric case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 9560b57cec5SDimitry Andric case MCBinaryExpr::Mul: Result = LHS * RHS; break; 9570b57cec5SDimitry Andric case MCBinaryExpr::NE: Result = LHS != RHS; break; 9580b57cec5SDimitry Andric case MCBinaryExpr::Or: Result = LHS | RHS; break; 959e8d8bef9SDimitry Andric case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; 9600b57cec5SDimitry Andric case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; 9610b57cec5SDimitry Andric case MCBinaryExpr::Sub: Result = LHS - RHS; break; 9620b57cec5SDimitry Andric case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric switch (Op) { 9660b57cec5SDimitry Andric default: 9670b57cec5SDimitry Andric Res = MCValue::get(Result); 9680b57cec5SDimitry Andric break; 9690b57cec5SDimitry Andric case MCBinaryExpr::EQ: 9700b57cec5SDimitry Andric case MCBinaryExpr::GT: 9710b57cec5SDimitry Andric case MCBinaryExpr::GTE: 9720b57cec5SDimitry Andric case MCBinaryExpr::LT: 9730b57cec5SDimitry Andric case MCBinaryExpr::LTE: 9740b57cec5SDimitry Andric case MCBinaryExpr::NE: 9750b57cec5SDimitry Andric // A comparison operator returns a -1 if true and 0 if false. 9760b57cec5SDimitry Andric Res = MCValue::get(Result ? -1 : 0); 9770b57cec5SDimitry Andric break; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric return true; 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 9850b57cec5SDimitry Andric } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric MCFragment *MCExpr::findAssociatedFragment() const { 9880b57cec5SDimitry Andric switch (getKind()) { 9890b57cec5SDimitry Andric case Target: 9900b57cec5SDimitry Andric // We never look through target specific expressions. 9910b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->findAssociatedFragment(); 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric case Constant: 9940b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric case SymbolRef: { 9970b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 9980b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 9990b57cec5SDimitry Andric return Sym.getFragment(); 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric case Unary: 10030b57cec5SDimitry Andric return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric case Binary: { 10060b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 10070b57cec5SDimitry Andric MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); 10080b57cec5SDimitry Andric MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric // If either is absolute, return the other. 10110b57cec5SDimitry Andric if (LHS_F == MCSymbol::AbsolutePseudoFragment) 10120b57cec5SDimitry Andric return RHS_F; 10130b57cec5SDimitry Andric if (RHS_F == MCSymbol::AbsolutePseudoFragment) 10140b57cec5SDimitry Andric return LHS_F; 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric // Not always correct, but probably the best we can do without more context. 10170b57cec5SDimitry Andric if (BE->getOpcode() == MCBinaryExpr::Sub) 10180b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric // Otherwise, return the first non-null fragment. 10210b57cec5SDimitry Andric return LHS_F ? LHS_F : RHS_F; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 10260b57cec5SDimitry Andric } 1027