Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCExpr.cpp
35233 views
//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/MC/MCExpr.h"9#include "llvm/ADT/Statistic.h"10#include "llvm/ADT/StringSwitch.h"11#include "llvm/Config/llvm-config.h"12#include "llvm/MC/MCAsmBackend.h"13#include "llvm/MC/MCAsmInfo.h"14#include "llvm/MC/MCAssembler.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCObjectWriter.h"17#include "llvm/MC/MCSymbol.h"18#include "llvm/MC/MCValue.h"19#include "llvm/Support/Casting.h"20#include "llvm/Support/Compiler.h"21#include "llvm/Support/Debug.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/raw_ostream.h"24#include <cassert>25#include <cstdint>2627using namespace llvm;2829#define DEBUG_TYPE "mcexpr"3031namespace {32namespace stats {3334STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");3536} // end namespace stats37} // end anonymous namespace3839void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {40switch (getKind()) {41case MCExpr::Target:42return cast<MCTargetExpr>(this)->printImpl(OS, MAI);43case MCExpr::Constant: {44auto Value = cast<MCConstantExpr>(*this).getValue();45auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat();46auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes();47if (Value < 0 && MAI && !MAI->supportsSignedData())48PrintInHex = true;49if (PrintInHex)50switch (SizeInBytes) {51default:52OS << "0x" << Twine::utohexstr(Value);53break;54case 1:55OS << format("0x%02" PRIx64, Value);56break;57case 2:58OS << format("0x%04" PRIx64, Value);59break;60case 4:61OS << format("0x%08" PRIx64, Value);62break;63case 8:64OS << format("0x%016" PRIx64, Value);65break;66}67else68OS << Value;69return;70}71case MCExpr::SymbolRef: {72const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);73const MCSymbol &Sym = SRE.getSymbol();74// Parenthesize names that start with $ so that they don't look like75// absolute names.76bool UseParens = MAI && MAI->useParensForDollarSignNames() && !InParens &&77Sym.getName().starts_with('$');7879if (UseParens) {80OS << '(';81Sym.print(OS, MAI);82OS << ')';83} else84Sym.print(OS, MAI);8586const MCSymbolRefExpr::VariantKind Kind = SRE.getKind();87if (Kind != MCSymbolRefExpr::VK_None) {88if (MAI && MAI->useParensForSymbolVariant()) // ARM89OS << '(' << MCSymbolRefExpr::getVariantKindName(Kind) << ')';90else91OS << '@' << MCSymbolRefExpr::getVariantKindName(Kind);92}9394return;95}9697case MCExpr::Unary: {98const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this);99switch (UE.getOpcode()) {100case MCUnaryExpr::LNot: OS << '!'; break;101case MCUnaryExpr::Minus: OS << '-'; break;102case MCUnaryExpr::Not: OS << '~'; break;103case MCUnaryExpr::Plus: OS << '+'; break;104}105bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary;106if (Binary) OS << "(";107UE.getSubExpr()->print(OS, MAI);108if (Binary) OS << ")";109return;110}111112case MCExpr::Binary: {113const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);114115// Only print parens around the LHS if it is non-trivial.116if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {117BE.getLHS()->print(OS, MAI);118} else {119OS << '(';120BE.getLHS()->print(OS, MAI);121OS << ')';122}123124switch (BE.getOpcode()) {125case MCBinaryExpr::Add:126// Print "X-42" instead of "X+-42".127if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {128if (RHSC->getValue() < 0) {129OS << RHSC->getValue();130return;131}132}133134OS << '+';135break;136case MCBinaryExpr::AShr: OS << ">>"; break;137case MCBinaryExpr::And: OS << '&'; break;138case MCBinaryExpr::Div: OS << '/'; break;139case MCBinaryExpr::EQ: OS << "=="; break;140case MCBinaryExpr::GT: OS << '>'; break;141case MCBinaryExpr::GTE: OS << ">="; break;142case MCBinaryExpr::LAnd: OS << "&&"; break;143case MCBinaryExpr::LOr: OS << "||"; break;144case MCBinaryExpr::LShr: OS << ">>"; break;145case MCBinaryExpr::LT: OS << '<'; break;146case MCBinaryExpr::LTE: OS << "<="; break;147case MCBinaryExpr::Mod: OS << '%'; break;148case MCBinaryExpr::Mul: OS << '*'; break;149case MCBinaryExpr::NE: OS << "!="; break;150case MCBinaryExpr::Or: OS << '|'; break;151case MCBinaryExpr::OrNot: OS << '!'; break;152case MCBinaryExpr::Shl: OS << "<<"; break;153case MCBinaryExpr::Sub: OS << '-'; break;154case MCBinaryExpr::Xor: OS << '^'; break;155}156157// Only print parens around the LHS if it is non-trivial.158if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {159BE.getRHS()->print(OS, MAI);160} else {161OS << '(';162BE.getRHS()->print(OS, MAI);163OS << ')';164}165return;166}167}168169llvm_unreachable("Invalid expression kind!");170}171172#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)173LLVM_DUMP_METHOD void MCExpr::dump() const {174dbgs() << *this;175dbgs() << '\n';176}177#endif178179/* *** */180181const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS,182const MCExpr *RHS, MCContext &Ctx,183SMLoc Loc) {184return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc);185}186187const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr,188MCContext &Ctx, SMLoc Loc) {189return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);190}191192const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx,193bool PrintInHex,194unsigned SizeInBytes) {195return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes);196}197198/* *** */199200MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind,201const MCAsmInfo *MAI, SMLoc Loc)202: MCExpr(MCExpr::SymbolRef, Loc,203encodeSubclassData(Kind, MAI->hasSubsectionsViaSymbols())),204Symbol(Symbol) {205assert(Symbol);206}207208const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym,209VariantKind Kind,210MCContext &Ctx, SMLoc Loc) {211return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc);212}213214const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind,215MCContext &Ctx) {216return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx);217}218219StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {220switch (Kind) {221// clang-format off222case VK_Invalid: return "<<invalid>>";223case VK_None: return "<<none>>";224225case VK_DTPOFF: return "DTPOFF";226case VK_DTPREL: return "DTPREL";227case VK_GOT: return "GOT";228case VK_GOTOFF: return "GOTOFF";229case VK_GOTREL: return "GOTREL";230case VK_PCREL: return "PCREL";231case VK_GOTPCREL: return "GOTPCREL";232case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX";233case VK_GOTTPOFF: return "GOTTPOFF";234case VK_GOTTPOFF_FDPIC: return "gottpoff_fdpic";235case VK_INDNTPOFF: return "INDNTPOFF";236case VK_NTPOFF: return "NTPOFF";237case VK_GOTNTPOFF: return "GOTNTPOFF";238case VK_PLT: return "PLT";239case VK_TLSGD: return "TLSGD";240case VK_TLSGD_FDPIC: return "tlsgd_fdpic";241case VK_TLSLD: return "TLSLD";242case VK_TLSLDM: return "TLSLDM";243case VK_TLSLDM_FDPIC: return "tlsldm_fdpic";244case VK_TPOFF: return "TPOFF";245case VK_TPREL: return "TPREL";246case VK_TLSCALL: return "tlscall";247case VK_TLSDESC: return "tlsdesc";248case VK_TLVP: return "TLVP";249case VK_TLVPPAGE: return "TLVPPAGE";250case VK_TLVPPAGEOFF: return "TLVPPAGEOFF";251case VK_PAGE: return "PAGE";252case VK_PAGEOFF: return "PAGEOFF";253case VK_GOTPAGE: return "GOTPAGE";254case VK_GOTPAGEOFF: return "GOTPAGEOFF";255case VK_SECREL: return "SECREL32";256case VK_SIZE: return "SIZE";257case VK_WEAKREF: return "WEAKREF";258case VK_FUNCDESC: return "FUNCDESC";259case VK_GOTFUNCDESC: return "GOTFUNCDESC";260case VK_GOTOFFFUNCDESC: return "GOTOFFFUNCDESC";261case VK_X86_ABS8: return "ABS8";262case VK_X86_PLTOFF: return "PLTOFF";263case VK_ARM_NONE: return "none";264case VK_ARM_GOT_PREL: return "GOT_PREL";265case VK_ARM_TARGET1: return "target1";266case VK_ARM_TARGET2: return "target2";267case VK_ARM_PREL31: return "prel31";268case VK_ARM_SBREL: return "sbrel";269case VK_ARM_TLSLDO: return "tlsldo";270case VK_ARM_TLSDESCSEQ: return "tlsdescseq";271case VK_AVR_NONE: return "none";272case VK_AVR_LO8: return "lo8";273case VK_AVR_HI8: return "hi8";274case VK_AVR_HLO8: return "hlo8";275case VK_AVR_DIFF8: return "diff8";276case VK_AVR_DIFF16: return "diff16";277case VK_AVR_DIFF32: return "diff32";278case VK_AVR_PM: return "pm";279case VK_PPC_LO: return "l";280case VK_PPC_HI: return "h";281case VK_PPC_HA: return "ha";282case VK_PPC_HIGH: return "high";283case VK_PPC_HIGHA: return "higha";284case VK_PPC_HIGHER: return "higher";285case VK_PPC_HIGHERA: return "highera";286case VK_PPC_HIGHEST: return "highest";287case VK_PPC_HIGHESTA: return "highesta";288case VK_PPC_GOT_LO: return "got@l";289case VK_PPC_GOT_HI: return "got@h";290case VK_PPC_GOT_HA: return "got@ha";291case VK_PPC_TOCBASE: return "tocbase";292case VK_PPC_TOC: return "toc";293case VK_PPC_TOC_LO: return "toc@l";294case VK_PPC_TOC_HI: return "toc@h";295case VK_PPC_TOC_HA: return "toc@ha";296case VK_PPC_U: return "u";297case VK_PPC_L: return "l";298case VK_PPC_DTPMOD: return "dtpmod";299case VK_PPC_TPREL_LO: return "tprel@l";300case VK_PPC_TPREL_HI: return "tprel@h";301case VK_PPC_TPREL_HA: return "tprel@ha";302case VK_PPC_TPREL_HIGH: return "tprel@high";303case VK_PPC_TPREL_HIGHA: return "tprel@higha";304case VK_PPC_TPREL_HIGHER: return "tprel@higher";305case VK_PPC_TPREL_HIGHERA: return "tprel@highera";306case VK_PPC_TPREL_HIGHEST: return "tprel@highest";307case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta";308case VK_PPC_DTPREL_LO: return "dtprel@l";309case VK_PPC_DTPREL_HI: return "dtprel@h";310case VK_PPC_DTPREL_HA: return "dtprel@ha";311case VK_PPC_DTPREL_HIGH: return "dtprel@high";312case VK_PPC_DTPREL_HIGHA: return "dtprel@higha";313case VK_PPC_DTPREL_HIGHER: return "dtprel@higher";314case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera";315case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest";316case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta";317case VK_PPC_GOT_TPREL: return "got@tprel";318case VK_PPC_GOT_TPREL_LO: return "got@tprel@l";319case VK_PPC_GOT_TPREL_HI: return "got@tprel@h";320case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha";321case VK_PPC_GOT_DTPREL: return "got@dtprel";322case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l";323case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h";324case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha";325case VK_PPC_TLS: return "tls";326case VK_PPC_GOT_TLSGD: return "got@tlsgd";327case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l";328case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h";329case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha";330case VK_PPC_TLSGD: return "tlsgd";331case VK_PPC_AIX_TLSGD:332return "gd";333case VK_PPC_AIX_TLSGDM:334return "m";335case VK_PPC_AIX_TLSIE:336return "ie";337case VK_PPC_AIX_TLSLE:338return "le";339case VK_PPC_AIX_TLSLD:340return "ld";341case VK_PPC_AIX_TLSML:342return "ml";343case VK_PPC_GOT_TLSLD: return "got@tlsld";344case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";345case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";346case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";347case VK_PPC_GOT_PCREL:348return "got@pcrel";349case VK_PPC_GOT_TLSGD_PCREL:350return "got@tlsgd@pcrel";351case VK_PPC_GOT_TLSLD_PCREL:352return "got@tlsld@pcrel";353case VK_PPC_GOT_TPREL_PCREL:354return "got@tprel@pcrel";355case VK_PPC_TLS_PCREL:356return "tls@pcrel";357case VK_PPC_TLSLD: return "tlsld";358case VK_PPC_LOCAL: return "local";359case VK_PPC_NOTOC: return "notoc";360case VK_PPC_PCREL_OPT: return "<<invalid>>";361case VK_COFF_IMGREL32: return "IMGREL";362case VK_Hexagon_LO16: return "LO16";363case VK_Hexagon_HI16: return "HI16";364case VK_Hexagon_GPREL: return "GPREL";365case VK_Hexagon_GD_GOT: return "GDGOT";366case VK_Hexagon_LD_GOT: return "LDGOT";367case VK_Hexagon_GD_PLT: return "GDPLT";368case VK_Hexagon_LD_PLT: return "LDPLT";369case VK_Hexagon_IE: return "IE";370case VK_Hexagon_IE_GOT: return "IEGOT";371case VK_WASM_TYPEINDEX: return "TYPEINDEX";372case VK_WASM_MBREL: return "MBREL";373case VK_WASM_TLSREL: return "TLSREL";374case VK_WASM_TBREL: return "TBREL";375case VK_WASM_GOT_TLS: return "GOT@TLS";376case VK_WASM_FUNCINDEX: return "FUNCINDEX";377case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";378case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";379case VK_AMDGPU_REL32_LO: return "rel32@lo";380case VK_AMDGPU_REL32_HI: return "rel32@hi";381case VK_AMDGPU_REL64: return "rel64";382case VK_AMDGPU_ABS32_LO: return "abs32@lo";383case VK_AMDGPU_ABS32_HI: return "abs32@hi";384case VK_VE_HI32: return "hi";385case VK_VE_LO32: return "lo";386case VK_VE_PC_HI32: return "pc_hi";387case VK_VE_PC_LO32: return "pc_lo";388case VK_VE_GOT_HI32: return "got_hi";389case VK_VE_GOT_LO32: return "got_lo";390case VK_VE_GOTOFF_HI32: return "gotoff_hi";391case VK_VE_GOTOFF_LO32: return "gotoff_lo";392case VK_VE_PLT_HI32: return "plt_hi";393case VK_VE_PLT_LO32: return "plt_lo";394case VK_VE_TLS_GD_HI32: return "tls_gd_hi";395case VK_VE_TLS_GD_LO32: return "tls_gd_lo";396case VK_VE_TPOFF_HI32: return "tpoff_hi";397case VK_VE_TPOFF_LO32: return "tpoff_lo";398// clang-format on399}400llvm_unreachable("Invalid variant kind");401}402403MCSymbolRefExpr::VariantKind404MCSymbolRefExpr::getVariantKindForName(StringRef Name) {405return StringSwitch<VariantKind>(Name.lower())406.Case("dtprel", VK_DTPREL)407.Case("dtpoff", VK_DTPOFF)408.Case("got", VK_GOT)409.Case("gotoff", VK_GOTOFF)410.Case("gotrel", VK_GOTREL)411.Case("pcrel", VK_PCREL)412.Case("gotpcrel", VK_GOTPCREL)413.Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX)414.Case("gottpoff", VK_GOTTPOFF)415.Case("indntpoff", VK_INDNTPOFF)416.Case("ntpoff", VK_NTPOFF)417.Case("gotntpoff", VK_GOTNTPOFF)418.Case("plt", VK_PLT)419.Case("tlscall", VK_TLSCALL)420.Case("tlsdesc", VK_TLSDESC)421.Case("tlsgd", VK_TLSGD)422.Case("tlsld", VK_TLSLD)423.Case("tlsldm", VK_TLSLDM)424.Case("tpoff", VK_TPOFF)425.Case("tprel", VK_TPREL)426.Case("tlvp", VK_TLVP)427.Case("tlvppage", VK_TLVPPAGE)428.Case("tlvppageoff", VK_TLVPPAGEOFF)429.Case("page", VK_PAGE)430.Case("pageoff", VK_PAGEOFF)431.Case("gotpage", VK_GOTPAGE)432.Case("gotpageoff", VK_GOTPAGEOFF)433.Case("imgrel", VK_COFF_IMGREL32)434.Case("secrel32", VK_SECREL)435.Case("size", VK_SIZE)436.Case("abs8", VK_X86_ABS8)437.Case("pltoff", VK_X86_PLTOFF)438.Case("l", VK_PPC_LO)439.Case("h", VK_PPC_HI)440.Case("ha", VK_PPC_HA)441.Case("high", VK_PPC_HIGH)442.Case("higha", VK_PPC_HIGHA)443.Case("higher", VK_PPC_HIGHER)444.Case("highera", VK_PPC_HIGHERA)445.Case("highest", VK_PPC_HIGHEST)446.Case("highesta", VK_PPC_HIGHESTA)447.Case("got@l", VK_PPC_GOT_LO)448.Case("got@h", VK_PPC_GOT_HI)449.Case("got@ha", VK_PPC_GOT_HA)450.Case("local", VK_PPC_LOCAL)451.Case("tocbase", VK_PPC_TOCBASE)452.Case("toc", VK_PPC_TOC)453.Case("toc@l", VK_PPC_TOC_LO)454.Case("toc@h", VK_PPC_TOC_HI)455.Case("toc@ha", VK_PPC_TOC_HA)456.Case("u", VK_PPC_U)457.Case("l", VK_PPC_L)458.Case("tls", VK_PPC_TLS)459.Case("dtpmod", VK_PPC_DTPMOD)460.Case("tprel@l", VK_PPC_TPREL_LO)461.Case("tprel@h", VK_PPC_TPREL_HI)462.Case("tprel@ha", VK_PPC_TPREL_HA)463.Case("tprel@high", VK_PPC_TPREL_HIGH)464.Case("tprel@higha", VK_PPC_TPREL_HIGHA)465.Case("tprel@higher", VK_PPC_TPREL_HIGHER)466.Case("tprel@highera", VK_PPC_TPREL_HIGHERA)467.Case("tprel@highest", VK_PPC_TPREL_HIGHEST)468.Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)469.Case("dtprel@l", VK_PPC_DTPREL_LO)470.Case("dtprel@h", VK_PPC_DTPREL_HI)471.Case("dtprel@ha", VK_PPC_DTPREL_HA)472.Case("dtprel@high", VK_PPC_DTPREL_HIGH)473.Case("dtprel@higha", VK_PPC_DTPREL_HIGHA)474.Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)475.Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)476.Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)477.Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)478.Case("got@tprel", VK_PPC_GOT_TPREL)479.Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)480.Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)481.Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)482.Case("got@dtprel", VK_PPC_GOT_DTPREL)483.Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)484.Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)485.Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)486.Case("got@tlsgd", VK_PPC_GOT_TLSGD)487.Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)488.Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)489.Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)490.Case("got@tlsld", VK_PPC_GOT_TLSLD)491.Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)492.Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)493.Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)494.Case("got@pcrel", VK_PPC_GOT_PCREL)495.Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL)496.Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL)497.Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL)498.Case("tls@pcrel", VK_PPC_TLS_PCREL)499.Case("notoc", VK_PPC_NOTOC)500.Case("gdgot", VK_Hexagon_GD_GOT)501.Case("gdplt", VK_Hexagon_GD_PLT)502.Case("iegot", VK_Hexagon_IE_GOT)503.Case("ie", VK_Hexagon_IE)504.Case("ldgot", VK_Hexagon_LD_GOT)505.Case("ldplt", VK_Hexagon_LD_PLT)506.Case("lo8", VK_AVR_LO8)507.Case("hi8", VK_AVR_HI8)508.Case("hlo8", VK_AVR_HLO8)509.Case("typeindex", VK_WASM_TYPEINDEX)510.Case("tbrel", VK_WASM_TBREL)511.Case("mbrel", VK_WASM_MBREL)512.Case("tlsrel", VK_WASM_TLSREL)513.Case("got@tls", VK_WASM_GOT_TLS)514.Case("funcindex", VK_WASM_FUNCINDEX)515.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)516.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)517.Case("rel32@lo", VK_AMDGPU_REL32_LO)518.Case("rel32@hi", VK_AMDGPU_REL32_HI)519.Case("rel64", VK_AMDGPU_REL64)520.Case("abs32@lo", VK_AMDGPU_ABS32_LO)521.Case("abs32@hi", VK_AMDGPU_ABS32_HI)522.Case("hi", VK_VE_HI32)523.Case("lo", VK_VE_LO32)524.Case("pc_hi", VK_VE_PC_HI32)525.Case("pc_lo", VK_VE_PC_LO32)526.Case("got_hi", VK_VE_GOT_HI32)527.Case("got_lo", VK_VE_GOT_LO32)528.Case("gotoff_hi", VK_VE_GOTOFF_HI32)529.Case("gotoff_lo", VK_VE_GOTOFF_LO32)530.Case("plt_hi", VK_VE_PLT_HI32)531.Case("plt_lo", VK_VE_PLT_LO32)532.Case("tls_gd_hi", VK_VE_TLS_GD_HI32)533.Case("tls_gd_lo", VK_VE_TLS_GD_LO32)534.Case("tpoff_hi", VK_VE_TPOFF_HI32)535.Case("tpoff_lo", VK_VE_TPOFF_LO32)536.Default(VK_Invalid);537}538539/* *** */540541void MCTargetExpr::anchor() {}542543/* *** */544545bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {546return evaluateAsAbsolute(Res, nullptr, nullptr, false);547}548549bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm,550const SectionAddrMap &Addrs) const {551// Setting InSet causes us to absolutize differences across sections and that552// is what the MachO writer uses Addrs for.553return evaluateAsAbsolute(Res, &Asm, &Addrs, true);554}555556bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {557return evaluateAsAbsolute(Res, &Asm, nullptr, false);558}559560bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {561return evaluateAsAbsolute(Res, Asm, nullptr, false);562}563564bool MCExpr::evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const {565return evaluateAsAbsolute(Res, &Asm, nullptr, true);566}567568bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,569const SectionAddrMap *Addrs, bool InSet) const {570MCValue Value;571572// Fast path constants.573if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) {574Res = CE->getValue();575return true;576}577578bool IsRelocatable =579evaluateAsRelocatableImpl(Value, Asm, nullptr, Addrs, InSet);580581// Record the current value.582Res = Value.getConstant();583584return IsRelocatable && Value.isAbsolute();585}586587/// Helper method for \see EvaluateSymbolAdd().588static void AttemptToFoldSymbolOffsetDifference(589const MCAssembler *Asm, const SectionAddrMap *Addrs, bool InSet,590const MCSymbolRefExpr *&A, const MCSymbolRefExpr *&B, int64_t &Addend) {591if (!A || !B)592return;593594const MCSymbol &SA = A->getSymbol();595const MCSymbol &SB = B->getSymbol();596597if (SA.isUndefined() || SB.isUndefined())598return;599600if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet))601return;602603auto FinalizeFolding = [&]() {604// Pointers to Thumb symbols need to have their low-bit set to allow605// for interworking.606if (Asm->isThumbFunc(&SA))607Addend |= 1;608609// Clear the symbol expr pointers to indicate we have folded these610// operands.611A = B = nullptr;612};613614const MCFragment *FA = SA.getFragment();615const MCFragment *FB = SB.getFragment();616const MCSection &SecA = *FA->getParent();617const MCSection &SecB = *FB->getParent();618if ((&SecA != &SecB) && !Addrs)619return;620621// When layout is available, we can generally compute the difference using the622// getSymbolOffset path, which also avoids the possible slow fragment walk.623// However, linker relaxation may cause incorrect fold of A-B if A and B are624// separated by a linker-relaxable instruction. If the section contains625// instructions and InSet is false (not expressions in directive like626// .size/.fill), disable the fast path.627bool Layout = Asm->hasLayout();628if (Layout && (InSet || !SecA.hasInstructions() ||629!(Asm->getContext().getTargetTriple().isRISCV() ||630Asm->getContext().getTargetTriple().isLoongArch()))) {631// If both symbols are in the same fragment, return the difference of their632// offsets. canGetFragmentOffset(FA) may be false.633if (FA == FB && !SA.isVariable() && !SB.isVariable()) {634Addend += SA.getOffset() - SB.getOffset();635return FinalizeFolding();636}637638// Eagerly evaluate when layout is finalized.639Addend += Asm->getSymbolOffset(A->getSymbol()) -640Asm->getSymbolOffset(B->getSymbol());641if (Addrs && (&SecA != &SecB))642Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB));643644FinalizeFolding();645} else {646// When layout is not finalized, our ability to resolve differences between647// symbols is limited to specific cases where the fragments between two648// symbols (including the fragments the symbols are defined in) are649// fixed-size fragments so the difference can be calculated. For example,650// this is important when the Subtarget is changed and a new MCDataFragment651// is created in the case of foo: instr; .arch_extension ext; instr .if . -652// foo.653if (SA.isVariable() || SB.isVariable())654return;655656// Try to find a constant displacement from FA to FB, add the displacement657// between the offset in FA of SA and the offset in FB of SB.658bool Reverse = false;659if (FA == FB)660Reverse = SA.getOffset() < SB.getOffset();661else662Reverse = FA->getLayoutOrder() < FB->getLayoutOrder();663664uint64_t SAOffset = SA.getOffset(), SBOffset = SB.getOffset();665int64_t Displacement = SA.getOffset() - SB.getOffset();666if (Reverse) {667std::swap(FA, FB);668std::swap(SAOffset, SBOffset);669Displacement *= -1;670}671672// Track whether B is before a relaxable instruction and whether A is after673// a relaxable instruction. If SA and SB are separated by a linker-relaxable674// instruction, the difference cannot be resolved as it may be changed by675// the linker.676bool BBeforeRelax = false, AAfterRelax = false;677for (auto FI = FB; FI; FI = FI->getNext()) {678auto DF = dyn_cast<MCDataFragment>(FI);679if (DF && DF->isLinkerRelaxable()) {680if (&*FI != FB || SBOffset != DF->getContents().size())681BBeforeRelax = true;682if (&*FI != FA || SAOffset == DF->getContents().size())683AAfterRelax = true;684if (BBeforeRelax && AAfterRelax)685return;686}687if (&*FI == FA) {688// If FA and FB belong to the same subsection, the loop will find FA and689// we can resolve the difference.690Addend += Reverse ? -Displacement : Displacement;691FinalizeFolding();692return;693}694695int64_t Num;696unsigned Count;697if (DF) {698Displacement += DF->getContents().size();699} else if (auto *AF = dyn_cast<MCAlignFragment>(FI);700AF && Layout && AF->hasEmitNops() &&701!Asm->getBackend().shouldInsertExtraNopBytesForCodeAlign(702*AF, Count)) {703Displacement += Asm->computeFragmentSize(*AF);704} else if (auto *FF = dyn_cast<MCFillFragment>(FI);705FF && FF->getNumValues().evaluateAsAbsolute(Num)) {706Displacement += Num * FF->getValueSize();707} else {708return;709}710}711}712}713714/// Evaluate the result of an add between (conceptually) two MCValues.715///716/// This routine conceptually attempts to construct an MCValue:717/// Result = (Result_A - Result_B + Result_Cst)718/// from two MCValue's LHS and RHS where719/// Result = LHS + RHS720/// and721/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).722///723/// This routine attempts to aggressively fold the operands such that the result724/// is representable in an MCValue, but may not always succeed.725///726/// \returns True on success, false if the result is not representable in an727/// MCValue.728729/// NOTE: It is really important to have both the Asm and Layout arguments.730/// They might look redundant, but this function can be used before layout731/// is done (see the object streamer for example) and having the Asm argument732/// lets us avoid relaxations early.733static bool evaluateSymbolicAdd(const MCAssembler *Asm,734const SectionAddrMap *Addrs, bool InSet,735const MCValue &LHS, const MCValue &RHS,736MCValue &Res) {737// FIXME: This routine (and other evaluation parts) are *incredibly* sloppy738// about dealing with modifiers. This will ultimately bite us, one day.739const MCSymbolRefExpr *LHS_A = LHS.getSymA();740const MCSymbolRefExpr *LHS_B = LHS.getSymB();741int64_t LHS_Cst = LHS.getConstant();742743const MCSymbolRefExpr *RHS_A = RHS.getSymA();744const MCSymbolRefExpr *RHS_B = RHS.getSymB();745int64_t RHS_Cst = RHS.getConstant();746747if (LHS.getRefKind() != RHS.getRefKind())748return false;749750// Fold the result constant immediately.751int64_t Result_Cst = LHS_Cst + RHS_Cst;752753// If we have a layout, we can fold resolved differences.754if (Asm) {755// First, fold out any differences which are fully resolved. By756// reassociating terms in757// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst).758// we have the four possible differences:759// (LHS_A - LHS_B),760// (LHS_A - RHS_B),761// (RHS_A - LHS_B),762// (RHS_A - RHS_B).763// Since we are attempting to be as aggressive as possible about folding, we764// attempt to evaluate each possible alternative.765AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, LHS_A, LHS_B,766Result_Cst);767AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, LHS_A, RHS_B,768Result_Cst);769AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, RHS_A, LHS_B,770Result_Cst);771AttemptToFoldSymbolOffsetDifference(Asm, Addrs, InSet, RHS_A, RHS_B,772Result_Cst);773}774775// We can't represent the addition or subtraction of two symbols.776if ((LHS_A && RHS_A) || (LHS_B && RHS_B))777return false;778779// At this point, we have at most one additive symbol and one subtractive780// symbol -- find them.781const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A;782const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B;783784Res = MCValue::get(A, B, Result_Cst);785return true;786}787788bool MCExpr::evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm,789const MCFixup *Fixup) const {790return evaluateAsRelocatableImpl(Res, Asm, Fixup, nullptr, false);791}792793bool MCExpr::evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const {794return evaluateAsRelocatableImpl(Res, &Asm, nullptr, nullptr, true);795}796797static bool canExpand(const MCSymbol &Sym, bool InSet) {798if (Sym.isWeakExternal())799return false;800801const MCExpr *Expr = Sym.getVariableValue();802const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);803if (Inner) {804if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)805return false;806}807808if (InSet)809return true;810return !Sym.isInSection();811}812813bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,814const MCFixup *Fixup,815const SectionAddrMap *Addrs,816bool InSet) const {817++stats::MCExprEvaluate;818switch (getKind()) {819case Target:820return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Asm, Fixup);821822case Constant:823Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());824return true;825826case SymbolRef: {827const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);828const MCSymbol &Sym = SRE->getSymbol();829const auto Kind = SRE->getKind();830bool Layout = Asm && Asm->hasLayout();831832// Evaluate recursively if this is a variable.833if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) &&834canExpand(Sym, InSet)) {835bool IsMachO = SRE->hasSubsectionsViaSymbols();836if (Sym.getVariableValue()->evaluateAsRelocatableImpl(837Res, Asm, Fixup, Addrs, InSet || IsMachO)) {838if (Kind != MCSymbolRefExpr::VK_None) {839if (Res.isAbsolute()) {840Res = MCValue::get(SRE, nullptr, 0);841return true;842}843// If the reference has a variant kind, we can only handle expressions844// which evaluate exactly to a single unadorned symbol. Attach the845// original VariantKind to SymA of the result.846if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() ||847Res.getSymB() || Res.getConstant())848return false;849Res =850MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(),851Kind, Asm->getContext()),852Res.getSymB(), Res.getConstant(), Res.getRefKind());853}854if (!IsMachO)855return true;856857const MCSymbolRefExpr *A = Res.getSymA();858const MCSymbolRefExpr *B = Res.getSymB();859// FIXME: This is small hack. Given860// a = b + 4861// .long a862// the OS X assembler will completely drop the 4. We should probably863// include it in the relocation or produce an error if that is not864// possible.865// Allow constant expressions.866if (!A && !B)867return true;868// Allows aliases with zero offset.869if (Res.getConstant() == 0 && (!A || !B))870return true;871}872}873874Res = MCValue::get(SRE, nullptr, 0);875return true;876}877878case Unary: {879const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);880MCValue Value;881882if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Fixup, Addrs,883InSet))884return false;885886switch (AUE->getOpcode()) {887case MCUnaryExpr::LNot:888if (!Value.isAbsolute())889return false;890Res = MCValue::get(!Value.getConstant());891break;892case MCUnaryExpr::Minus:893/// -(a - b + const) ==> (b - a - const)894if (Value.getSymA() && !Value.getSymB())895return false;896897// The cast avoids undefined behavior if the constant is INT64_MIN.898Res = MCValue::get(Value.getSymB(), Value.getSymA(),899-(uint64_t)Value.getConstant());900break;901case MCUnaryExpr::Not:902if (!Value.isAbsolute())903return false;904Res = MCValue::get(~Value.getConstant());905break;906case MCUnaryExpr::Plus:907Res = Value;908break;909}910911return true;912}913914case Binary: {915const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);916MCValue LHSValue, RHSValue;917918if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Fixup, Addrs,919InSet) ||920!ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Fixup, Addrs,921InSet)) {922// Check if both are Target Expressions, see if we can compare them.923if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) {924if (const MCTargetExpr *R = dyn_cast<MCTargetExpr>(ABE->getRHS())) {925switch (ABE->getOpcode()) {926case MCBinaryExpr::EQ:927Res = MCValue::get(L->isEqualTo(R) ? -1 : 0);928return true;929case MCBinaryExpr::NE:930Res = MCValue::get(L->isEqualTo(R) ? 0 : -1);931return true;932default:933break;934}935}936}937return false;938}939940// We only support a few operations on non-constant expressions, handle941// those first.942if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) {943switch (ABE->getOpcode()) {944default:945return false;946case MCBinaryExpr::Sub:947// Negate RHS and add.948// The cast avoids undefined behavior if the constant is INT64_MIN.949return evaluateSymbolicAdd(950Asm, Addrs, InSet, LHSValue,951MCValue::get(RHSValue.getSymB(), RHSValue.getSymA(),952-(uint64_t)RHSValue.getConstant(),953RHSValue.getRefKind()),954Res);955956case MCBinaryExpr::Add:957return evaluateSymbolicAdd(958Asm, Addrs, InSet, LHSValue,959MCValue::get(RHSValue.getSymA(), RHSValue.getSymB(),960RHSValue.getConstant(), RHSValue.getRefKind()),961Res);962}963}964965// FIXME: We need target hooks for the evaluation. It may be limited in966// width, and gas defines the result of comparisons differently from967// Apple as.968int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant();969int64_t Result = 0;970auto Op = ABE->getOpcode();971switch (Op) {972case MCBinaryExpr::AShr: Result = LHS >> RHS; break;973case MCBinaryExpr::Add: Result = LHS + RHS; break;974case MCBinaryExpr::And: Result = LHS & RHS; break;975case MCBinaryExpr::Div:976case MCBinaryExpr::Mod:977// Handle division by zero. gas just emits a warning and keeps going,978// we try to be stricter.979// FIXME: Currently the caller of this function has no way to understand980// we're bailing out because of 'division by zero'. Therefore, it will981// emit a 'expected relocatable expression' error. It would be nice to982// change this code to emit a better diagnostic.983if (RHS == 0)984return false;985if (ABE->getOpcode() == MCBinaryExpr::Div)986Result = LHS / RHS;987else988Result = LHS % RHS;989break;990case MCBinaryExpr::EQ: Result = LHS == RHS; break;991case MCBinaryExpr::GT: Result = LHS > RHS; break;992case MCBinaryExpr::GTE: Result = LHS >= RHS; break;993case MCBinaryExpr::LAnd: Result = LHS && RHS; break;994case MCBinaryExpr::LOr: Result = LHS || RHS; break;995case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break;996case MCBinaryExpr::LT: Result = LHS < RHS; break;997case MCBinaryExpr::LTE: Result = LHS <= RHS; break;998case MCBinaryExpr::Mul: Result = LHS * RHS; break;999case MCBinaryExpr::NE: Result = LHS != RHS; break;1000case MCBinaryExpr::Or: Result = LHS | RHS; break;1001case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break;1002case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break;1003case MCBinaryExpr::Sub: Result = LHS - RHS; break;1004case MCBinaryExpr::Xor: Result = LHS ^ RHS; break;1005}10061007switch (Op) {1008default:1009Res = MCValue::get(Result);1010break;1011case MCBinaryExpr::EQ:1012case MCBinaryExpr::GT:1013case MCBinaryExpr::GTE:1014case MCBinaryExpr::LT:1015case MCBinaryExpr::LTE:1016case MCBinaryExpr::NE:1017// A comparison operator returns a -1 if true and 0 if false.1018Res = MCValue::get(Result ? -1 : 0);1019break;1020}10211022return true;1023}1024}10251026llvm_unreachable("Invalid assembly expression kind!");1027}10281029MCFragment *MCExpr::findAssociatedFragment() const {1030switch (getKind()) {1031case Target:1032// We never look through target specific expressions.1033return cast<MCTargetExpr>(this)->findAssociatedFragment();10341035case Constant:1036return MCSymbol::AbsolutePseudoFragment;10371038case SymbolRef: {1039const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);1040const MCSymbol &Sym = SRE->getSymbol();1041return Sym.getFragment();1042}10431044case Unary:1045return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment();10461047case Binary: {1048const MCBinaryExpr *BE = cast<MCBinaryExpr>(this);1049MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment();1050MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment();10511052// If either is absolute, return the other.1053if (LHS_F == MCSymbol::AbsolutePseudoFragment)1054return RHS_F;1055if (RHS_F == MCSymbol::AbsolutePseudoFragment)1056return LHS_F;10571058// Not always correct, but probably the best we can do without more context.1059if (BE->getOpcode() == MCBinaryExpr::Sub)1060return MCSymbol::AbsolutePseudoFragment;10611062// Otherwise, return the first non-null fragment.1063return LHS_F ? LHS_F : RHS_F;1064}1065}10661067llvm_unreachable("Invalid assembly expression kind!");1068}106910701071