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/StringExtras.h" 120b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 130b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 140b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h" 150b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCAsmLayout.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 220b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 230b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 240b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 270b57cec5SDimitry Andric #include <cassert> 280b57cec5SDimitry Andric #include <cstdint> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace llvm; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #define DEBUG_TYPE "mcexpr" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace { 350b57cec5SDimitry Andric namespace stats { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric } // end namespace stats 400b57cec5SDimitry Andric } // end anonymous namespace 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { 430b57cec5SDimitry Andric switch (getKind()) { 440b57cec5SDimitry Andric case MCExpr::Target: 450b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->printImpl(OS, MAI); 460b57cec5SDimitry Andric case MCExpr::Constant: { 470b57cec5SDimitry Andric auto Value = cast<MCConstantExpr>(*this).getValue(); 480b57cec5SDimitry Andric auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat(); 490b57cec5SDimitry Andric if (PrintInHex) 500b57cec5SDimitry Andric OS << "0x" << Twine::utohexstr(Value); 510b57cec5SDimitry Andric else 520b57cec5SDimitry Andric OS << Value; 530b57cec5SDimitry Andric return; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric case MCExpr::SymbolRef: { 560b57cec5SDimitry Andric const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); 570b57cec5SDimitry Andric const MCSymbol &Sym = SRE.getSymbol(); 580b57cec5SDimitry Andric // Parenthesize names that start with $ so that they don't look like 590b57cec5SDimitry Andric // absolute names. 600b57cec5SDimitry Andric bool UseParens = 610b57cec5SDimitry Andric !InParens && !Sym.getName().empty() && Sym.getName()[0] == '$'; 620b57cec5SDimitry Andric if (UseParens) { 630b57cec5SDimitry Andric OS << '('; 640b57cec5SDimitry Andric Sym.print(OS, MAI); 650b57cec5SDimitry Andric OS << ')'; 660b57cec5SDimitry Andric } else 670b57cec5SDimitry Andric Sym.print(OS, MAI); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (SRE.getKind() != MCSymbolRefExpr::VK_None) 700b57cec5SDimitry Andric SRE.printVariantKind(OS); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric return; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric case MCExpr::Unary: { 760b57cec5SDimitry Andric const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 770b57cec5SDimitry Andric switch (UE.getOpcode()) { 780b57cec5SDimitry Andric case MCUnaryExpr::LNot: OS << '!'; break; 790b57cec5SDimitry Andric case MCUnaryExpr::Minus: OS << '-'; break; 800b57cec5SDimitry Andric case MCUnaryExpr::Not: OS << '~'; break; 810b57cec5SDimitry Andric case MCUnaryExpr::Plus: OS << '+'; break; 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary; 840b57cec5SDimitry Andric if (Binary) OS << "("; 850b57cec5SDimitry Andric UE.getSubExpr()->print(OS, MAI); 860b57cec5SDimitry Andric if (Binary) OS << ")"; 870b57cec5SDimitry Andric return; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric case MCExpr::Binary: { 910b57cec5SDimitry Andric const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Only print parens around the LHS if it is non-trivial. 940b57cec5SDimitry Andric if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 950b57cec5SDimitry Andric BE.getLHS()->print(OS, MAI); 960b57cec5SDimitry Andric } else { 970b57cec5SDimitry Andric OS << '('; 980b57cec5SDimitry Andric BE.getLHS()->print(OS, MAI); 990b57cec5SDimitry Andric OS << ')'; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric switch (BE.getOpcode()) { 1030b57cec5SDimitry Andric case MCBinaryExpr::Add: 1040b57cec5SDimitry Andric // Print "X-42" instead of "X+-42". 1050b57cec5SDimitry Andric if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 1060b57cec5SDimitry Andric if (RHSC->getValue() < 0) { 1070b57cec5SDimitry Andric OS << RHSC->getValue(); 1080b57cec5SDimitry Andric return; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric OS << '+'; 1130b57cec5SDimitry Andric break; 1140b57cec5SDimitry Andric case MCBinaryExpr::AShr: OS << ">>"; break; 1150b57cec5SDimitry Andric case MCBinaryExpr::And: OS << '&'; break; 1160b57cec5SDimitry Andric case MCBinaryExpr::Div: OS << '/'; break; 1170b57cec5SDimitry Andric case MCBinaryExpr::EQ: OS << "=="; break; 1180b57cec5SDimitry Andric case MCBinaryExpr::GT: OS << '>'; break; 1190b57cec5SDimitry Andric case MCBinaryExpr::GTE: OS << ">="; break; 1200b57cec5SDimitry Andric case MCBinaryExpr::LAnd: OS << "&&"; break; 1210b57cec5SDimitry Andric case MCBinaryExpr::LOr: OS << "||"; break; 1220b57cec5SDimitry Andric case MCBinaryExpr::LShr: OS << ">>"; break; 1230b57cec5SDimitry Andric case MCBinaryExpr::LT: OS << '<'; break; 1240b57cec5SDimitry Andric case MCBinaryExpr::LTE: OS << "<="; break; 1250b57cec5SDimitry Andric case MCBinaryExpr::Mod: OS << '%'; break; 1260b57cec5SDimitry Andric case MCBinaryExpr::Mul: OS << '*'; break; 1270b57cec5SDimitry Andric case MCBinaryExpr::NE: OS << "!="; break; 1280b57cec5SDimitry Andric case MCBinaryExpr::Or: OS << '|'; break; 1290b57cec5SDimitry Andric case MCBinaryExpr::Shl: OS << "<<"; break; 1300b57cec5SDimitry Andric case MCBinaryExpr::Sub: OS << '-'; break; 1310b57cec5SDimitry Andric case MCBinaryExpr::Xor: OS << '^'; break; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // Only print parens around the LHS if it is non-trivial. 1350b57cec5SDimitry Andric if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 1360b57cec5SDimitry Andric BE.getRHS()->print(OS, MAI); 1370b57cec5SDimitry Andric } else { 1380b57cec5SDimitry Andric OS << '('; 1390b57cec5SDimitry Andric BE.getRHS()->print(OS, MAI); 1400b57cec5SDimitry Andric OS << ')'; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric return; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric llvm_unreachable("Invalid expression kind!"); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1500b57cec5SDimitry Andric LLVM_DUMP_METHOD void MCExpr::dump() const { 1510b57cec5SDimitry Andric dbgs() << *this; 1520b57cec5SDimitry Andric dbgs() << '\n'; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric #endif 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /* *** */ 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, 1590b57cec5SDimitry Andric const MCExpr *RHS, MCContext &Ctx, 1600b57cec5SDimitry Andric SMLoc Loc) { 1610b57cec5SDimitry Andric return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, 1650b57cec5SDimitry Andric MCContext &Ctx, SMLoc Loc) { 1660b57cec5SDimitry Andric return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, 1700b57cec5SDimitry Andric bool PrintInHex) { 1710b57cec5SDimitry Andric return new (Ctx) MCConstantExpr(Value, PrintInHex); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric /* *** */ 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, 1770b57cec5SDimitry Andric const MCAsmInfo *MAI, SMLoc Loc) 1780b57cec5SDimitry Andric : MCExpr(MCExpr::SymbolRef, Loc), Kind(Kind), 1790b57cec5SDimitry Andric UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), 1800b57cec5SDimitry Andric HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), 1810b57cec5SDimitry Andric Symbol(Symbol) { 1820b57cec5SDimitry Andric assert(Symbol); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, 1860b57cec5SDimitry Andric VariantKind Kind, 1870b57cec5SDimitry Andric MCContext &Ctx, SMLoc Loc) { 1880b57cec5SDimitry Andric return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, 1920b57cec5SDimitry Andric MCContext &Ctx) { 1930b57cec5SDimitry Andric return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 1970b57cec5SDimitry Andric switch (Kind) { 1980b57cec5SDimitry Andric case VK_Invalid: return "<<invalid>>"; 1990b57cec5SDimitry Andric case VK_None: return "<<none>>"; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric case VK_DTPOFF: return "DTPOFF"; 2020b57cec5SDimitry Andric case VK_DTPREL: return "DTPREL"; 2030b57cec5SDimitry Andric case VK_GOT: return "GOT"; 2040b57cec5SDimitry Andric case VK_GOTOFF: return "GOTOFF"; 2050b57cec5SDimitry Andric case VK_GOTREL: return "GOTREL"; 2060b57cec5SDimitry Andric case VK_GOTPCREL: return "GOTPCREL"; 2070b57cec5SDimitry Andric case VK_GOTTPOFF: return "GOTTPOFF"; 2080b57cec5SDimitry Andric case VK_INDNTPOFF: return "INDNTPOFF"; 2090b57cec5SDimitry Andric case VK_NTPOFF: return "NTPOFF"; 2100b57cec5SDimitry Andric case VK_GOTNTPOFF: return "GOTNTPOFF"; 2110b57cec5SDimitry Andric case VK_PLT: return "PLT"; 2120b57cec5SDimitry Andric case VK_TLSGD: return "TLSGD"; 2130b57cec5SDimitry Andric case VK_TLSLD: return "TLSLD"; 2140b57cec5SDimitry Andric case VK_TLSLDM: return "TLSLDM"; 2150b57cec5SDimitry Andric case VK_TPOFF: return "TPOFF"; 2160b57cec5SDimitry Andric case VK_TPREL: return "TPREL"; 2170b57cec5SDimitry Andric case VK_TLSCALL: return "tlscall"; 2180b57cec5SDimitry Andric case VK_TLSDESC: return "tlsdesc"; 2190b57cec5SDimitry Andric case VK_TLVP: return "TLVP"; 2200b57cec5SDimitry Andric case VK_TLVPPAGE: return "TLVPPAGE"; 2210b57cec5SDimitry Andric case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; 2220b57cec5SDimitry Andric case VK_PAGE: return "PAGE"; 2230b57cec5SDimitry Andric case VK_PAGEOFF: return "PAGEOFF"; 2240b57cec5SDimitry Andric case VK_GOTPAGE: return "GOTPAGE"; 2250b57cec5SDimitry Andric case VK_GOTPAGEOFF: return "GOTPAGEOFF"; 2260b57cec5SDimitry Andric case VK_SECREL: return "SECREL32"; 2270b57cec5SDimitry Andric case VK_SIZE: return "SIZE"; 2280b57cec5SDimitry Andric case VK_WEAKREF: return "WEAKREF"; 2290b57cec5SDimitry Andric case VK_X86_ABS8: return "ABS8"; 2300b57cec5SDimitry Andric case VK_ARM_NONE: return "none"; 2310b57cec5SDimitry Andric case VK_ARM_GOT_PREL: return "GOT_PREL"; 2320b57cec5SDimitry Andric case VK_ARM_TARGET1: return "target1"; 2330b57cec5SDimitry Andric case VK_ARM_TARGET2: return "target2"; 2340b57cec5SDimitry Andric case VK_ARM_PREL31: return "prel31"; 2350b57cec5SDimitry Andric case VK_ARM_SBREL: return "sbrel"; 2360b57cec5SDimitry Andric case VK_ARM_TLSLDO: return "tlsldo"; 2370b57cec5SDimitry Andric case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; 2380b57cec5SDimitry Andric case VK_AVR_NONE: return "none"; 2390b57cec5SDimitry Andric case VK_AVR_LO8: return "lo8"; 2400b57cec5SDimitry Andric case VK_AVR_HI8: return "hi8"; 2410b57cec5SDimitry Andric case VK_AVR_HLO8: return "hlo8"; 2420b57cec5SDimitry Andric case VK_AVR_DIFF8: return "diff8"; 2430b57cec5SDimitry Andric case VK_AVR_DIFF16: return "diff16"; 2440b57cec5SDimitry Andric case VK_AVR_DIFF32: return "diff32"; 2450b57cec5SDimitry Andric case VK_PPC_LO: return "l"; 2460b57cec5SDimitry Andric case VK_PPC_HI: return "h"; 2470b57cec5SDimitry Andric case VK_PPC_HA: return "ha"; 2480b57cec5SDimitry Andric case VK_PPC_HIGH: return "high"; 2490b57cec5SDimitry Andric case VK_PPC_HIGHA: return "higha"; 2500b57cec5SDimitry Andric case VK_PPC_HIGHER: return "higher"; 2510b57cec5SDimitry Andric case VK_PPC_HIGHERA: return "highera"; 2520b57cec5SDimitry Andric case VK_PPC_HIGHEST: return "highest"; 2530b57cec5SDimitry Andric case VK_PPC_HIGHESTA: return "highesta"; 2540b57cec5SDimitry Andric case VK_PPC_GOT_LO: return "got@l"; 2550b57cec5SDimitry Andric case VK_PPC_GOT_HI: return "got@h"; 2560b57cec5SDimitry Andric case VK_PPC_GOT_HA: return "got@ha"; 2570b57cec5SDimitry Andric case VK_PPC_TOCBASE: return "tocbase"; 2580b57cec5SDimitry Andric case VK_PPC_TOC: return "toc"; 2590b57cec5SDimitry Andric case VK_PPC_TOC_LO: return "toc@l"; 2600b57cec5SDimitry Andric case VK_PPC_TOC_HI: return "toc@h"; 2610b57cec5SDimitry Andric case VK_PPC_TOC_HA: return "toc@ha"; 2628bcb0991SDimitry Andric case VK_PPC_U: return "u"; 2638bcb0991SDimitry Andric case VK_PPC_L: return "l"; 2640b57cec5SDimitry Andric case VK_PPC_DTPMOD: return "dtpmod"; 2650b57cec5SDimitry Andric case VK_PPC_TPREL_LO: return "tprel@l"; 2660b57cec5SDimitry Andric case VK_PPC_TPREL_HI: return "tprel@h"; 2670b57cec5SDimitry Andric case VK_PPC_TPREL_HA: return "tprel@ha"; 2680b57cec5SDimitry Andric case VK_PPC_TPREL_HIGH: return "tprel@high"; 2690b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHA: return "tprel@higha"; 2700b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHER: return "tprel@higher"; 2710b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; 2720b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; 2730b57cec5SDimitry Andric case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; 2740b57cec5SDimitry Andric case VK_PPC_DTPREL_LO: return "dtprel@l"; 2750b57cec5SDimitry Andric case VK_PPC_DTPREL_HI: return "dtprel@h"; 2760b57cec5SDimitry Andric case VK_PPC_DTPREL_HA: return "dtprel@ha"; 2770b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGH: return "dtprel@high"; 2780b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHA: return "dtprel@higha"; 2790b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; 2800b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; 2810b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; 2820b57cec5SDimitry Andric case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; 2830b57cec5SDimitry Andric case VK_PPC_GOT_TPREL: return "got@tprel"; 2840b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; 2850b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; 2860b57cec5SDimitry Andric case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; 2870b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL: return "got@dtprel"; 2880b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; 2890b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; 2900b57cec5SDimitry Andric case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; 2910b57cec5SDimitry Andric case VK_PPC_TLS: return "tls"; 2920b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD: return "got@tlsgd"; 2930b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; 2940b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; 2950b57cec5SDimitry Andric case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; 2960b57cec5SDimitry Andric case VK_PPC_TLSGD: return "tlsgd"; 2970b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD: return "got@tlsld"; 2980b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 2990b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; 3000b57cec5SDimitry Andric case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 3010b57cec5SDimitry Andric case VK_PPC_TLSLD: return "tlsld"; 3020b57cec5SDimitry Andric case VK_PPC_LOCAL: return "local"; 3030b57cec5SDimitry Andric case VK_COFF_IMGREL32: return "IMGREL"; 3040b57cec5SDimitry Andric case VK_Hexagon_PCREL: return "PCREL"; 3050b57cec5SDimitry Andric case VK_Hexagon_LO16: return "LO16"; 3060b57cec5SDimitry Andric case VK_Hexagon_HI16: return "HI16"; 3070b57cec5SDimitry Andric case VK_Hexagon_GPREL: return "GPREL"; 3080b57cec5SDimitry Andric case VK_Hexagon_GD_GOT: return "GDGOT"; 3090b57cec5SDimitry Andric case VK_Hexagon_LD_GOT: return "LDGOT"; 3100b57cec5SDimitry Andric case VK_Hexagon_GD_PLT: return "GDPLT"; 3110b57cec5SDimitry Andric case VK_Hexagon_LD_PLT: return "LDPLT"; 3120b57cec5SDimitry Andric case VK_Hexagon_IE: return "IE"; 3130b57cec5SDimitry Andric case VK_Hexagon_IE_GOT: return "IEGOT"; 3140b57cec5SDimitry Andric case VK_WASM_TYPEINDEX: return "TYPEINDEX"; 3150b57cec5SDimitry Andric case VK_WASM_MBREL: return "MBREL"; 3160b57cec5SDimitry Andric case VK_WASM_TBREL: return "TBREL"; 3170b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; 3180b57cec5SDimitry Andric case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; 3190b57cec5SDimitry Andric case VK_AMDGPU_REL32_LO: return "rel32@lo"; 3200b57cec5SDimitry Andric case VK_AMDGPU_REL32_HI: return "rel32@hi"; 3210b57cec5SDimitry Andric case VK_AMDGPU_REL64: return "rel64"; 3220b57cec5SDimitry Andric case VK_AMDGPU_ABS32_LO: return "abs32@lo"; 3230b57cec5SDimitry Andric case VK_AMDGPU_ABS32_HI: return "abs32@hi"; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric llvm_unreachable("Invalid variant kind"); 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind 3290b57cec5SDimitry Andric MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 3300b57cec5SDimitry Andric return StringSwitch<VariantKind>(Name.lower()) 3310b57cec5SDimitry Andric .Case("dtprel", VK_DTPREL) 3320b57cec5SDimitry Andric .Case("dtpoff", VK_DTPOFF) 3330b57cec5SDimitry Andric .Case("got", VK_GOT) 3340b57cec5SDimitry Andric .Case("gotoff", VK_GOTOFF) 3350b57cec5SDimitry Andric .Case("gotrel", VK_GOTREL) 3360b57cec5SDimitry Andric .Case("gotpcrel", VK_GOTPCREL) 3370b57cec5SDimitry Andric .Case("gottpoff", VK_GOTTPOFF) 3380b57cec5SDimitry Andric .Case("indntpoff", VK_INDNTPOFF) 3390b57cec5SDimitry Andric .Case("ntpoff", VK_NTPOFF) 3400b57cec5SDimitry Andric .Case("gotntpoff", VK_GOTNTPOFF) 3410b57cec5SDimitry Andric .Case("plt", VK_PLT) 3420b57cec5SDimitry Andric .Case("tlscall", VK_TLSCALL) 3430b57cec5SDimitry Andric .Case("tlsdesc", VK_TLSDESC) 3440b57cec5SDimitry Andric .Case("tlsgd", VK_TLSGD) 3450b57cec5SDimitry Andric .Case("tlsld", VK_TLSLD) 3460b57cec5SDimitry Andric .Case("tlsldm", VK_TLSLDM) 3470b57cec5SDimitry Andric .Case("tpoff", VK_TPOFF) 3480b57cec5SDimitry Andric .Case("tprel", VK_TPREL) 3490b57cec5SDimitry Andric .Case("tlvp", VK_TLVP) 3500b57cec5SDimitry Andric .Case("tlvppage", VK_TLVPPAGE) 3510b57cec5SDimitry Andric .Case("tlvppageoff", VK_TLVPPAGEOFF) 3520b57cec5SDimitry Andric .Case("page", VK_PAGE) 3530b57cec5SDimitry Andric .Case("pageoff", VK_PAGEOFF) 3540b57cec5SDimitry Andric .Case("gotpage", VK_GOTPAGE) 3550b57cec5SDimitry Andric .Case("gotpageoff", VK_GOTPAGEOFF) 3560b57cec5SDimitry Andric .Case("imgrel", VK_COFF_IMGREL32) 3570b57cec5SDimitry Andric .Case("secrel32", VK_SECREL) 3580b57cec5SDimitry Andric .Case("size", VK_SIZE) 3590b57cec5SDimitry Andric .Case("abs8", VK_X86_ABS8) 3600b57cec5SDimitry Andric .Case("l", VK_PPC_LO) 3610b57cec5SDimitry Andric .Case("h", VK_PPC_HI) 3620b57cec5SDimitry Andric .Case("ha", VK_PPC_HA) 3630b57cec5SDimitry Andric .Case("high", VK_PPC_HIGH) 3640b57cec5SDimitry Andric .Case("higha", VK_PPC_HIGHA) 3650b57cec5SDimitry Andric .Case("higher", VK_PPC_HIGHER) 3660b57cec5SDimitry Andric .Case("highera", VK_PPC_HIGHERA) 3670b57cec5SDimitry Andric .Case("highest", VK_PPC_HIGHEST) 3680b57cec5SDimitry Andric .Case("highesta", VK_PPC_HIGHESTA) 3690b57cec5SDimitry Andric .Case("got@l", VK_PPC_GOT_LO) 3700b57cec5SDimitry Andric .Case("got@h", VK_PPC_GOT_HI) 3710b57cec5SDimitry Andric .Case("got@ha", VK_PPC_GOT_HA) 3720b57cec5SDimitry Andric .Case("local", VK_PPC_LOCAL) 3730b57cec5SDimitry Andric .Case("tocbase", VK_PPC_TOCBASE) 3740b57cec5SDimitry Andric .Case("toc", VK_PPC_TOC) 3750b57cec5SDimitry Andric .Case("toc@l", VK_PPC_TOC_LO) 3760b57cec5SDimitry Andric .Case("toc@h", VK_PPC_TOC_HI) 3770b57cec5SDimitry Andric .Case("toc@ha", VK_PPC_TOC_HA) 3788bcb0991SDimitry Andric .Case("u", VK_PPC_U) 3798bcb0991SDimitry Andric .Case("l", VK_PPC_L) 3800b57cec5SDimitry Andric .Case("tls", VK_PPC_TLS) 3810b57cec5SDimitry Andric .Case("dtpmod", VK_PPC_DTPMOD) 3820b57cec5SDimitry Andric .Case("tprel@l", VK_PPC_TPREL_LO) 3830b57cec5SDimitry Andric .Case("tprel@h", VK_PPC_TPREL_HI) 3840b57cec5SDimitry Andric .Case("tprel@ha", VK_PPC_TPREL_HA) 3850b57cec5SDimitry Andric .Case("tprel@high", VK_PPC_TPREL_HIGH) 3860b57cec5SDimitry Andric .Case("tprel@higha", VK_PPC_TPREL_HIGHA) 3870b57cec5SDimitry Andric .Case("tprel@higher", VK_PPC_TPREL_HIGHER) 3880b57cec5SDimitry Andric .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) 3890b57cec5SDimitry Andric .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) 3900b57cec5SDimitry Andric .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) 3910b57cec5SDimitry Andric .Case("dtprel@l", VK_PPC_DTPREL_LO) 3920b57cec5SDimitry Andric .Case("dtprel@h", VK_PPC_DTPREL_HI) 3930b57cec5SDimitry Andric .Case("dtprel@ha", VK_PPC_DTPREL_HA) 3940b57cec5SDimitry Andric .Case("dtprel@high", VK_PPC_DTPREL_HIGH) 3950b57cec5SDimitry Andric .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) 3960b57cec5SDimitry Andric .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) 3970b57cec5SDimitry Andric .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) 3980b57cec5SDimitry Andric .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) 3990b57cec5SDimitry Andric .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) 4000b57cec5SDimitry Andric .Case("got@tprel", VK_PPC_GOT_TPREL) 4010b57cec5SDimitry Andric .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 4020b57cec5SDimitry Andric .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) 4030b57cec5SDimitry Andric .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 4040b57cec5SDimitry Andric .Case("got@dtprel", VK_PPC_GOT_DTPREL) 4050b57cec5SDimitry Andric .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) 4060b57cec5SDimitry Andric .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) 4070b57cec5SDimitry Andric .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) 4080b57cec5SDimitry Andric .Case("got@tlsgd", VK_PPC_GOT_TLSGD) 4090b57cec5SDimitry Andric .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 4100b57cec5SDimitry Andric .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) 4110b57cec5SDimitry Andric .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 4120b57cec5SDimitry Andric .Case("got@tlsld", VK_PPC_GOT_TLSLD) 4130b57cec5SDimitry Andric .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 4140b57cec5SDimitry Andric .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) 4150b57cec5SDimitry Andric .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 4160b57cec5SDimitry Andric .Case("gdgot", VK_Hexagon_GD_GOT) 4170b57cec5SDimitry Andric .Case("gdplt", VK_Hexagon_GD_PLT) 4180b57cec5SDimitry Andric .Case("iegot", VK_Hexagon_IE_GOT) 4190b57cec5SDimitry Andric .Case("ie", VK_Hexagon_IE) 4200b57cec5SDimitry Andric .Case("ldgot", VK_Hexagon_LD_GOT) 4210b57cec5SDimitry Andric .Case("ldplt", VK_Hexagon_LD_PLT) 4220b57cec5SDimitry Andric .Case("pcrel", VK_Hexagon_PCREL) 4230b57cec5SDimitry Andric .Case("none", VK_ARM_NONE) 4240b57cec5SDimitry Andric .Case("got_prel", VK_ARM_GOT_PREL) 4250b57cec5SDimitry Andric .Case("target1", VK_ARM_TARGET1) 4260b57cec5SDimitry Andric .Case("target2", VK_ARM_TARGET2) 4270b57cec5SDimitry Andric .Case("prel31", VK_ARM_PREL31) 4280b57cec5SDimitry Andric .Case("sbrel", VK_ARM_SBREL) 4290b57cec5SDimitry Andric .Case("tlsldo", VK_ARM_TLSLDO) 4300b57cec5SDimitry Andric .Case("lo8", VK_AVR_LO8) 4310b57cec5SDimitry Andric .Case("hi8", VK_AVR_HI8) 4320b57cec5SDimitry Andric .Case("hlo8", VK_AVR_HLO8) 4330b57cec5SDimitry Andric .Case("typeindex", VK_WASM_TYPEINDEX) 4340b57cec5SDimitry Andric .Case("tbrel", VK_WASM_TBREL) 4350b57cec5SDimitry Andric .Case("mbrel", VK_WASM_MBREL) 4360b57cec5SDimitry Andric .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) 4370b57cec5SDimitry Andric .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) 4380b57cec5SDimitry Andric .Case("rel32@lo", VK_AMDGPU_REL32_LO) 4390b57cec5SDimitry Andric .Case("rel32@hi", VK_AMDGPU_REL32_HI) 4400b57cec5SDimitry Andric .Case("rel64", VK_AMDGPU_REL64) 4410b57cec5SDimitry Andric .Case("abs32@lo", VK_AMDGPU_ABS32_LO) 4420b57cec5SDimitry Andric .Case("abs32@hi", VK_AMDGPU_ABS32_HI) 4430b57cec5SDimitry Andric .Default(VK_Invalid); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { 4470b57cec5SDimitry Andric if (UseParensForSymbolVariant) 4480b57cec5SDimitry Andric OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; 4490b57cec5SDimitry Andric else 4500b57cec5SDimitry Andric OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric /* *** */ 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric void MCTargetExpr::anchor() {} 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric /* *** */ 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { 4608bcb0991SDimitry Andric return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 4640b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 4658bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, 4690b57cec5SDimitry Andric const MCAsmLayout &Layout, 4700b57cec5SDimitry Andric const SectionAddrMap &Addrs) const { 4718bcb0991SDimitry Andric // Setting InSet causes us to absolutize differences across sections and that 4728bcb0991SDimitry Andric // is what the MachO writer uses Addrs for. 4738bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 4778bcb0991SDimitry Andric return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { 4818bcb0991SDimitry Andric return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric bool MCExpr::evaluateKnownAbsolute(int64_t &Res, 4850b57cec5SDimitry Andric const MCAsmLayout &Layout) const { 4860b57cec5SDimitry Andric return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, 4870b57cec5SDimitry Andric true); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 4910b57cec5SDimitry Andric const MCAsmLayout *Layout, 4920b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet) const { 4930b57cec5SDimitry Andric MCValue Value; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric // Fast path constants. 4960b57cec5SDimitry Andric if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 4970b57cec5SDimitry Andric Res = CE->getValue(); 4980b57cec5SDimitry Andric return true; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric bool IsRelocatable = 5020b57cec5SDimitry Andric evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric // Record the current value. 5050b57cec5SDimitry Andric Res = Value.getConstant(); 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric return IsRelocatable && Value.isAbsolute(); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric /// Helper method for \see EvaluateSymbolAdd(). 5110b57cec5SDimitry Andric static void AttemptToFoldSymbolOffsetDifference( 5120b57cec5SDimitry Andric const MCAssembler *Asm, const MCAsmLayout *Layout, 5130b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, 5140b57cec5SDimitry Andric const MCSymbolRefExpr *&B, int64_t &Addend) { 5150b57cec5SDimitry Andric if (!A || !B) 5160b57cec5SDimitry Andric return; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric const MCSymbol &SA = A->getSymbol(); 5190b57cec5SDimitry Andric const MCSymbol &SB = B->getSymbol(); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric if (SA.isUndefined() || SB.isUndefined()) 5220b57cec5SDimitry Andric return; 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 5250b57cec5SDimitry Andric return; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric if (SA.getFragment() == SB.getFragment() && !SA.isVariable() && 5280b57cec5SDimitry Andric !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) { 5290b57cec5SDimitry Andric Addend += (SA.getOffset() - SB.getOffset()); 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric // Pointers to Thumb symbols need to have their low-bit set to allow 5320b57cec5SDimitry Andric // for interworking. 5330b57cec5SDimitry Andric if (Asm->isThumbFunc(&SA)) 5340b57cec5SDimitry Andric Addend |= 1; 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // If symbol is labeled as micromips, we set low-bit to ensure 5370b57cec5SDimitry Andric // correct offset in .gcc_except_table 5380b57cec5SDimitry Andric if (Asm->getBackend().isMicroMips(&SA)) 5390b57cec5SDimitry Andric Addend |= 1; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric // Clear the symbol expr pointers to indicate we have folded these 5420b57cec5SDimitry Andric // operands. 5430b57cec5SDimitry Andric A = B = nullptr; 5440b57cec5SDimitry Andric return; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric if (!Layout) 5480b57cec5SDimitry Andric return; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric const MCSection &SecA = *SA.getFragment()->getParent(); 5510b57cec5SDimitry Andric const MCSection &SecB = *SB.getFragment()->getParent(); 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andric if ((&SecA != &SecB) && !Addrs) 5540b57cec5SDimitry Andric return; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric // Eagerly evaluate. 5570b57cec5SDimitry Andric Addend += Layout->getSymbolOffset(A->getSymbol()) - 5580b57cec5SDimitry Andric Layout->getSymbolOffset(B->getSymbol()); 5590b57cec5SDimitry Andric if (Addrs && (&SecA != &SecB)) 5600b57cec5SDimitry Andric Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // Pointers to Thumb symbols need to have their low-bit set to allow 5630b57cec5SDimitry Andric // for interworking. 5640b57cec5SDimitry Andric if (Asm->isThumbFunc(&SA)) 5650b57cec5SDimitry Andric Addend |= 1; 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric // If symbol is labeled as micromips, we set low-bit to ensure 5680b57cec5SDimitry Andric // correct offset in .gcc_except_table 5690b57cec5SDimitry Andric if (Asm->getBackend().isMicroMips(&SA)) 5700b57cec5SDimitry Andric Addend |= 1; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric // Clear the symbol expr pointers to indicate we have folded these 5730b57cec5SDimitry Andric // operands. 5740b57cec5SDimitry Andric A = B = nullptr; 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric static bool canFold(const MCAssembler *Asm, const MCSymbolRefExpr *A, 5780b57cec5SDimitry Andric const MCSymbolRefExpr *B, bool InSet) { 5790b57cec5SDimitry Andric if (InSet) 5800b57cec5SDimitry Andric return true; 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric if (!Asm->getBackend().requiresDiffExpressionRelocations()) 5830b57cec5SDimitry Andric return true; 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric const MCSymbol &CheckSym = A ? A->getSymbol() : B->getSymbol(); 5860b57cec5SDimitry Andric if (!CheckSym.isInSection()) 5870b57cec5SDimitry Andric return true; 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric if (!CheckSym.getSection().hasInstructions()) 5900b57cec5SDimitry Andric return true; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric return false; 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric /// Evaluate the result of an add between (conceptually) two MCValues. 5960b57cec5SDimitry Andric /// 5970b57cec5SDimitry Andric /// This routine conceptually attempts to construct an MCValue: 5980b57cec5SDimitry Andric /// Result = (Result_A - Result_B + Result_Cst) 5990b57cec5SDimitry Andric /// from two MCValue's LHS and RHS where 6000b57cec5SDimitry Andric /// Result = LHS + RHS 6010b57cec5SDimitry Andric /// and 6020b57cec5SDimitry Andric /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 6030b57cec5SDimitry Andric /// 604*480093f4SDimitry Andric /// This routine attempts to aggressively fold the operands such that the result 6050b57cec5SDimitry Andric /// is representable in an MCValue, but may not always succeed. 6060b57cec5SDimitry Andric /// 6070b57cec5SDimitry Andric /// \returns True on success, false if the result is not representable in an 6080b57cec5SDimitry Andric /// MCValue. 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric /// NOTE: It is really important to have both the Asm and Layout arguments. 6110b57cec5SDimitry Andric /// They might look redundant, but this function can be used before layout 6120b57cec5SDimitry Andric /// is done (see the object streamer for example) and having the Asm argument 6130b57cec5SDimitry Andric /// lets us avoid relaxations early. 6140b57cec5SDimitry Andric static bool 6150b57cec5SDimitry Andric EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, 6160b57cec5SDimitry Andric const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, 6170b57cec5SDimitry Andric const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, 6180b57cec5SDimitry Andric int64_t RHS_Cst, MCValue &Res) { 6190b57cec5SDimitry Andric // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 6200b57cec5SDimitry Andric // about dealing with modifiers. This will ultimately bite us, one day. 6210b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 6220b57cec5SDimitry Andric const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 6230b57cec5SDimitry Andric int64_t LHS_Cst = LHS.getConstant(); 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric // Fold the result constant immediately. 6260b57cec5SDimitry Andric int64_t Result_Cst = LHS_Cst + RHS_Cst; 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric assert((!Layout || Asm) && 6290b57cec5SDimitry Andric "Must have an assembler object if layout is given!"); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric // If we have a layout, we can fold resolved differences. Do not do this if 6320b57cec5SDimitry Andric // the backend requires this to be emitted as individual relocations, unless 6330b57cec5SDimitry Andric // the InSet flag is set to get the current difference anyway (used for 6340b57cec5SDimitry Andric // example to calculate symbol sizes). 6350b57cec5SDimitry Andric if (Asm && canFold(Asm, LHS_A, LHS_B, InSet)) { 6360b57cec5SDimitry Andric // First, fold out any differences which are fully resolved. By 6370b57cec5SDimitry Andric // reassociating terms in 6380b57cec5SDimitry Andric // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 6390b57cec5SDimitry Andric // we have the four possible differences: 6400b57cec5SDimitry Andric // (LHS_A - LHS_B), 6410b57cec5SDimitry Andric // (LHS_A - RHS_B), 6420b57cec5SDimitry Andric // (RHS_A - LHS_B), 6430b57cec5SDimitry Andric // (RHS_A - RHS_B). 6440b57cec5SDimitry Andric // Since we are attempting to be as aggressive as possible about folding, we 6450b57cec5SDimitry Andric // attempt to evaluate each possible alternative. 6460b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 6470b57cec5SDimitry Andric Result_Cst); 6480b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 6490b57cec5SDimitry Andric Result_Cst); 6500b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 6510b57cec5SDimitry Andric Result_Cst); 6520b57cec5SDimitry Andric AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 6530b57cec5SDimitry Andric Result_Cst); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric // We can't represent the addition or subtraction of two symbols. 6570b57cec5SDimitry Andric if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 6580b57cec5SDimitry Andric return false; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric // At this point, we have at most one additive symbol and one subtractive 6610b57cec5SDimitry Andric // symbol -- find them. 6620b57cec5SDimitry Andric const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 6630b57cec5SDimitry Andric const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric Res = MCValue::get(A, B, Result_Cst); 6660b57cec5SDimitry Andric return true; 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatable(MCValue &Res, 6700b57cec5SDimitry Andric const MCAsmLayout *Layout, 6710b57cec5SDimitry Andric const MCFixup *Fixup) const { 6720b57cec5SDimitry Andric MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; 6730b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, 6740b57cec5SDimitry Andric false); 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { 6780b57cec5SDimitry Andric MCAssembler *Assembler = &Layout.getAssembler(); 6790b57cec5SDimitry Andric return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, 6800b57cec5SDimitry Andric true); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric static bool canExpand(const MCSymbol &Sym, bool InSet) { 6840b57cec5SDimitry Andric const MCExpr *Expr = Sym.getVariableValue(); 6850b57cec5SDimitry Andric const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); 6860b57cec5SDimitry Andric if (Inner) { 6870b57cec5SDimitry Andric if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) 6880b57cec5SDimitry Andric return false; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric if (InSet) 6920b57cec5SDimitry Andric return true; 6930b57cec5SDimitry Andric return !Sym.isInSection(); 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 6970b57cec5SDimitry Andric const MCAsmLayout *Layout, 6980b57cec5SDimitry Andric const MCFixup *Fixup, 6990b57cec5SDimitry Andric const SectionAddrMap *Addrs, 7000b57cec5SDimitry Andric bool InSet) const { 7010b57cec5SDimitry Andric ++stats::MCExprEvaluate; 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric switch (getKind()) { 7040b57cec5SDimitry Andric case Target: 7050b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, 7060b57cec5SDimitry Andric Fixup); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric case Constant: 7090b57cec5SDimitry Andric Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 7100b57cec5SDimitry Andric return true; 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric case SymbolRef: { 7130b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 7140b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric // Evaluate recursively if this is a variable. 7170b57cec5SDimitry Andric if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None && 7180b57cec5SDimitry Andric canExpand(Sym, InSet)) { 7190b57cec5SDimitry Andric bool IsMachO = SRE->hasSubsectionsViaSymbols(); 7200b57cec5SDimitry Andric if (Sym.getVariableValue()->evaluateAsRelocatableImpl( 7210b57cec5SDimitry Andric Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { 7220b57cec5SDimitry Andric if (!IsMachO) 7230b57cec5SDimitry Andric return true; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric const MCSymbolRefExpr *A = Res.getSymA(); 7260b57cec5SDimitry Andric const MCSymbolRefExpr *B = Res.getSymB(); 7270b57cec5SDimitry Andric // FIXME: This is small hack. Given 7280b57cec5SDimitry Andric // a = b + 4 7290b57cec5SDimitry Andric // .long a 7300b57cec5SDimitry Andric // the OS X assembler will completely drop the 4. We should probably 7310b57cec5SDimitry Andric // include it in the relocation or produce an error if that is not 7320b57cec5SDimitry Andric // possible. 7330b57cec5SDimitry Andric // Allow constant expressions. 7340b57cec5SDimitry Andric if (!A && !B) 7350b57cec5SDimitry Andric return true; 7360b57cec5SDimitry Andric // Allows aliases with zero offset. 7370b57cec5SDimitry Andric if (Res.getConstant() == 0 && (!A || !B)) 7380b57cec5SDimitry Andric return true; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric Res = MCValue::get(SRE, nullptr, 0); 7430b57cec5SDimitry Andric return true; 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric case Unary: { 7470b57cec5SDimitry Andric const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 7480b57cec5SDimitry Andric MCValue Value; 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, 7510b57cec5SDimitry Andric Addrs, InSet)) 7520b57cec5SDimitry Andric return false; 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric switch (AUE->getOpcode()) { 7550b57cec5SDimitry Andric case MCUnaryExpr::LNot: 7560b57cec5SDimitry Andric if (!Value.isAbsolute()) 7570b57cec5SDimitry Andric return false; 7580b57cec5SDimitry Andric Res = MCValue::get(!Value.getConstant()); 7590b57cec5SDimitry Andric break; 7600b57cec5SDimitry Andric case MCUnaryExpr::Minus: 7610b57cec5SDimitry Andric /// -(a - b + const) ==> (b - a - const) 7620b57cec5SDimitry Andric if (Value.getSymA() && !Value.getSymB()) 7630b57cec5SDimitry Andric return false; 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 7660b57cec5SDimitry Andric Res = MCValue::get(Value.getSymB(), Value.getSymA(), 7670b57cec5SDimitry Andric -(uint64_t)Value.getConstant()); 7680b57cec5SDimitry Andric break; 7690b57cec5SDimitry Andric case MCUnaryExpr::Not: 7700b57cec5SDimitry Andric if (!Value.isAbsolute()) 7710b57cec5SDimitry Andric return false; 7720b57cec5SDimitry Andric Res = MCValue::get(~Value.getConstant()); 7730b57cec5SDimitry Andric break; 7740b57cec5SDimitry Andric case MCUnaryExpr::Plus: 7750b57cec5SDimitry Andric Res = Value; 7760b57cec5SDimitry Andric break; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric return true; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric case Binary: { 7830b57cec5SDimitry Andric const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 7840b57cec5SDimitry Andric MCValue LHSValue, RHSValue; 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, 7870b57cec5SDimitry Andric Addrs, InSet) || 7880b57cec5SDimitry Andric !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, 7890b57cec5SDimitry Andric Addrs, InSet)) { 7900b57cec5SDimitry Andric // Check if both are Target Expressions, see if we can compare them. 7910b57cec5SDimitry Andric if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) 7920b57cec5SDimitry Andric if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) { 7930b57cec5SDimitry Andric switch (ABE->getOpcode()) { 7940b57cec5SDimitry Andric case MCBinaryExpr::EQ: 7950b57cec5SDimitry Andric Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0); 7960b57cec5SDimitry Andric return true; 7970b57cec5SDimitry Andric case MCBinaryExpr::NE: 7980b57cec5SDimitry Andric Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1); 7990b57cec5SDimitry Andric return true; 8000b57cec5SDimitry Andric default: break; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric return false; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric // We only support a few operations on non-constant expressions, handle 8070b57cec5SDimitry Andric // those first. 8080b57cec5SDimitry Andric if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 8090b57cec5SDimitry Andric switch (ABE->getOpcode()) { 8100b57cec5SDimitry Andric default: 8110b57cec5SDimitry Andric return false; 8120b57cec5SDimitry Andric case MCBinaryExpr::Sub: 8130b57cec5SDimitry Andric // Negate RHS and add. 8140b57cec5SDimitry Andric // The cast avoids undefined behavior if the constant is INT64_MIN. 8150b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 8160b57cec5SDimitry Andric RHSValue.getSymB(), RHSValue.getSymA(), 8170b57cec5SDimitry Andric -(uint64_t)RHSValue.getConstant(), Res); 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric case MCBinaryExpr::Add: 8200b57cec5SDimitry Andric return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 8210b57cec5SDimitry Andric RHSValue.getSymA(), RHSValue.getSymB(), 8220b57cec5SDimitry Andric RHSValue.getConstant(), Res); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // FIXME: We need target hooks for the evaluation. It may be limited in 8270b57cec5SDimitry Andric // width, and gas defines the result of comparisons differently from 8280b57cec5SDimitry Andric // Apple as. 8290b57cec5SDimitry Andric int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 8300b57cec5SDimitry Andric int64_t Result = 0; 8310b57cec5SDimitry Andric auto Op = ABE->getOpcode(); 8320b57cec5SDimitry Andric switch (Op) { 8330b57cec5SDimitry Andric case MCBinaryExpr::AShr: Result = LHS >> RHS; break; 8340b57cec5SDimitry Andric case MCBinaryExpr::Add: Result = LHS + RHS; break; 8350b57cec5SDimitry Andric case MCBinaryExpr::And: Result = LHS & RHS; break; 8360b57cec5SDimitry Andric case MCBinaryExpr::Div: 8370b57cec5SDimitry Andric case MCBinaryExpr::Mod: 8380b57cec5SDimitry Andric // Handle division by zero. gas just emits a warning and keeps going, 8390b57cec5SDimitry Andric // we try to be stricter. 8400b57cec5SDimitry Andric // FIXME: Currently the caller of this function has no way to understand 8410b57cec5SDimitry Andric // we're bailing out because of 'division by zero'. Therefore, it will 8420b57cec5SDimitry Andric // emit a 'expected relocatable expression' error. It would be nice to 8430b57cec5SDimitry Andric // change this code to emit a better diagnostic. 8440b57cec5SDimitry Andric if (RHS == 0) 8450b57cec5SDimitry Andric return false; 8460b57cec5SDimitry Andric if (ABE->getOpcode() == MCBinaryExpr::Div) 8470b57cec5SDimitry Andric Result = LHS / RHS; 8480b57cec5SDimitry Andric else 8490b57cec5SDimitry Andric Result = LHS % RHS; 8500b57cec5SDimitry Andric break; 8510b57cec5SDimitry Andric case MCBinaryExpr::EQ: Result = LHS == RHS; break; 8520b57cec5SDimitry Andric case MCBinaryExpr::GT: Result = LHS > RHS; break; 8530b57cec5SDimitry Andric case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 8540b57cec5SDimitry Andric case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 8550b57cec5SDimitry Andric case MCBinaryExpr::LOr: Result = LHS || RHS; break; 8560b57cec5SDimitry Andric case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; 8570b57cec5SDimitry Andric case MCBinaryExpr::LT: Result = LHS < RHS; break; 8580b57cec5SDimitry Andric case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 8590b57cec5SDimitry Andric case MCBinaryExpr::Mul: Result = LHS * RHS; break; 8600b57cec5SDimitry Andric case MCBinaryExpr::NE: Result = LHS != RHS; break; 8610b57cec5SDimitry Andric case MCBinaryExpr::Or: Result = LHS | RHS; break; 8620b57cec5SDimitry Andric case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; 8630b57cec5SDimitry Andric case MCBinaryExpr::Sub: Result = LHS - RHS; break; 8640b57cec5SDimitry Andric case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric switch (Op) { 8680b57cec5SDimitry Andric default: 8690b57cec5SDimitry Andric Res = MCValue::get(Result); 8700b57cec5SDimitry Andric break; 8710b57cec5SDimitry Andric case MCBinaryExpr::EQ: 8720b57cec5SDimitry Andric case MCBinaryExpr::GT: 8730b57cec5SDimitry Andric case MCBinaryExpr::GTE: 8740b57cec5SDimitry Andric case MCBinaryExpr::LT: 8750b57cec5SDimitry Andric case MCBinaryExpr::LTE: 8760b57cec5SDimitry Andric case MCBinaryExpr::NE: 8770b57cec5SDimitry Andric // A comparison operator returns a -1 if true and 0 if false. 8780b57cec5SDimitry Andric Res = MCValue::get(Result ? -1 : 0); 8790b57cec5SDimitry Andric break; 8800b57cec5SDimitry Andric } 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric return true; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric MCFragment *MCExpr::findAssociatedFragment() const { 8900b57cec5SDimitry Andric switch (getKind()) { 8910b57cec5SDimitry Andric case Target: 8920b57cec5SDimitry Andric // We never look through target specific expressions. 8930b57cec5SDimitry Andric return cast<MCTargetExpr>(this)->findAssociatedFragment(); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric case Constant: 8960b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric case SymbolRef: { 8990b57cec5SDimitry Andric const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 9000b57cec5SDimitry Andric const MCSymbol &Sym = SRE->getSymbol(); 9010b57cec5SDimitry Andric return Sym.getFragment(); 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric case Unary: 9050b57cec5SDimitry Andric return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric case Binary: { 9080b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 9090b57cec5SDimitry Andric MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); 9100b57cec5SDimitry Andric MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric // If either is absolute, return the other. 9130b57cec5SDimitry Andric if (LHS_F == MCSymbol::AbsolutePseudoFragment) 9140b57cec5SDimitry Andric return RHS_F; 9150b57cec5SDimitry Andric if (RHS_F == MCSymbol::AbsolutePseudoFragment) 9160b57cec5SDimitry Andric return LHS_F; 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric // Not always correct, but probably the best we can do without more context. 9190b57cec5SDimitry Andric if (BE->getOpcode() == MCBinaryExpr::Sub) 9200b57cec5SDimitry Andric return MCSymbol::AbsolutePseudoFragment; 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric // Otherwise, return the first non-null fragment. 9230b57cec5SDimitry Andric return LHS_F ? LHS_F : RHS_F; 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric llvm_unreachable("Invalid assembly expression kind!"); 9280b57cec5SDimitry Andric } 929