10b57cec5SDimitry Andric //===-- AArch64MCExpr.cpp - AArch64 specific MC expression classes --------===// 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 // This file contains the implementation of the assembly expression modifiers 100b57cec5SDimitry Andric // accepted by the AArch64 architecture (e.g. ":lo12:", ":gottprel_g1:", ...). 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "AArch64MCExpr.h" 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 2081ad6265SDimitry Andric #include "llvm/Support/Casting.h" 210b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #define DEBUG_TYPE "aarch64symbolrefexpr" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric const AArch64MCExpr *AArch64MCExpr::create(const MCExpr *Expr, VariantKind Kind, 280b57cec5SDimitry Andric MCContext &Ctx) { 290b57cec5SDimitry Andric return new (Ctx) AArch64MCExpr(Expr, Kind); 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric StringRef AArch64MCExpr::getVariantKindName() const { 330b57cec5SDimitry Andric switch (static_cast<uint32_t>(getKind())) { 340b57cec5SDimitry Andric case VK_CALL: return ""; 350b57cec5SDimitry Andric case VK_LO12: return ":lo12:"; 360b57cec5SDimitry Andric case VK_ABS_G3: return ":abs_g3:"; 370b57cec5SDimitry Andric case VK_ABS_G2: return ":abs_g2:"; 380b57cec5SDimitry Andric case VK_ABS_G2_S: return ":abs_g2_s:"; 390b57cec5SDimitry Andric case VK_ABS_G2_NC: return ":abs_g2_nc:"; 400b57cec5SDimitry Andric case VK_ABS_G1: return ":abs_g1:"; 410b57cec5SDimitry Andric case VK_ABS_G1_S: return ":abs_g1_s:"; 420b57cec5SDimitry Andric case VK_ABS_G1_NC: return ":abs_g1_nc:"; 430b57cec5SDimitry Andric case VK_ABS_G0: return ":abs_g0:"; 440b57cec5SDimitry Andric case VK_ABS_G0_S: return ":abs_g0_s:"; 450b57cec5SDimitry Andric case VK_ABS_G0_NC: return ":abs_g0_nc:"; 468bcb0991SDimitry Andric case VK_PREL_G3: return ":prel_g3:"; 478bcb0991SDimitry Andric case VK_PREL_G2: return ":prel_g2:"; 488bcb0991SDimitry Andric case VK_PREL_G2_NC: return ":prel_g2_nc:"; 498bcb0991SDimitry Andric case VK_PREL_G1: return ":prel_g1:"; 508bcb0991SDimitry Andric case VK_PREL_G1_NC: return ":prel_g1_nc:"; 518bcb0991SDimitry Andric case VK_PREL_G0: return ":prel_g0:"; 528bcb0991SDimitry Andric case VK_PREL_G0_NC: return ":prel_g0_nc:"; 530b57cec5SDimitry Andric case VK_DTPREL_G2: return ":dtprel_g2:"; 540b57cec5SDimitry Andric case VK_DTPREL_G1: return ":dtprel_g1:"; 550b57cec5SDimitry Andric case VK_DTPREL_G1_NC: return ":dtprel_g1_nc:"; 560b57cec5SDimitry Andric case VK_DTPREL_G0: return ":dtprel_g0:"; 570b57cec5SDimitry Andric case VK_DTPREL_G0_NC: return ":dtprel_g0_nc:"; 580b57cec5SDimitry Andric case VK_DTPREL_HI12: return ":dtprel_hi12:"; 590b57cec5SDimitry Andric case VK_DTPREL_LO12: return ":dtprel_lo12:"; 600b57cec5SDimitry Andric case VK_DTPREL_LO12_NC: return ":dtprel_lo12_nc:"; 610b57cec5SDimitry Andric case VK_TPREL_G2: return ":tprel_g2:"; 620b57cec5SDimitry Andric case VK_TPREL_G1: return ":tprel_g1:"; 630b57cec5SDimitry Andric case VK_TPREL_G1_NC: return ":tprel_g1_nc:"; 640b57cec5SDimitry Andric case VK_TPREL_G0: return ":tprel_g0:"; 650b57cec5SDimitry Andric case VK_TPREL_G0_NC: return ":tprel_g0_nc:"; 660b57cec5SDimitry Andric case VK_TPREL_HI12: return ":tprel_hi12:"; 670b57cec5SDimitry Andric case VK_TPREL_LO12: return ":tprel_lo12:"; 680b57cec5SDimitry Andric case VK_TPREL_LO12_NC: return ":tprel_lo12_nc:"; 690b57cec5SDimitry Andric case VK_TLSDESC_LO12: return ":tlsdesc_lo12:"; 700b57cec5SDimitry Andric case VK_ABS_PAGE: return ""; 710b57cec5SDimitry Andric case VK_ABS_PAGE_NC: return ":pg_hi21_nc:"; 720b57cec5SDimitry Andric case VK_GOT: return ":got:"; 730b57cec5SDimitry Andric case VK_GOT_PAGE: return ":got:"; 74e8d8bef9SDimitry Andric case VK_GOT_PAGE_LO15: return ":gotpage_lo15:"; 750b57cec5SDimitry Andric case VK_GOT_LO12: return ":got_lo12:"; 760b57cec5SDimitry Andric case VK_GOTTPREL: return ":gottprel:"; 770b57cec5SDimitry Andric case VK_GOTTPREL_PAGE: return ":gottprel:"; 780b57cec5SDimitry Andric case VK_GOTTPREL_LO12_NC: return ":gottprel_lo12:"; 790b57cec5SDimitry Andric case VK_GOTTPREL_G1: return ":gottprel_g1:"; 800b57cec5SDimitry Andric case VK_GOTTPREL_G0_NC: return ":gottprel_g0_nc:"; 810b57cec5SDimitry Andric case VK_TLSDESC: return ""; 820b57cec5SDimitry Andric case VK_TLSDESC_PAGE: return ":tlsdesc:"; 830b57cec5SDimitry Andric case VK_SECREL_LO12: return ":secrel_lo12:"; 840b57cec5SDimitry Andric case VK_SECREL_HI12: return ":secrel_hi12:"; 850b57cec5SDimitry Andric default: 860b57cec5SDimitry Andric llvm_unreachable("Invalid ELF symbol kind"); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void AArch64MCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 910b57cec5SDimitry Andric OS << getVariantKindName(); 920b57cec5SDimitry Andric Expr->print(OS, MAI); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric void AArch64MCExpr::visitUsedExpr(MCStreamer &Streamer) const { 960b57cec5SDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric MCFragment *AArch64MCExpr::findAssociatedFragment() const { 1000b57cec5SDimitry Andric llvm_unreachable("FIXME: what goes here?"); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric bool AArch64MCExpr::evaluateAsRelocatableImpl(MCValue &Res, 104*0fca6ea1SDimitry Andric const MCAssembler *Asm, 1050b57cec5SDimitry Andric const MCFixup *Fixup) const { 106*0fca6ea1SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup)) 1070b57cec5SDimitry Andric return false; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric Res = 1100b57cec5SDimitry Andric MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric return true; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 1160b57cec5SDimitry Andric switch (Expr->getKind()) { 1170b57cec5SDimitry Andric case MCExpr::Target: 1180b57cec5SDimitry Andric llvm_unreachable("Can't handle nested target expression"); 1190b57cec5SDimitry Andric break; 1200b57cec5SDimitry Andric case MCExpr::Constant: 1210b57cec5SDimitry Andric break; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric case MCExpr::Binary: { 1240b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 1250b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 1260b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 1270b57cec5SDimitry Andric break; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric case MCExpr::SymbolRef: { 1310b57cec5SDimitry Andric // We're known to be under a TLS fixup, so any symbol should be 1320b57cec5SDimitry Andric // modified. There should be only one. 1330b57cec5SDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 1340b57cec5SDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 1350b57cec5SDimitry Andric break; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric case MCExpr::Unary: 1390b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 1400b57cec5SDimitry Andric break; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric void AArch64MCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 1450b57cec5SDimitry Andric switch (getSymbolLoc(Kind)) { 1460b57cec5SDimitry Andric default: 1470b57cec5SDimitry Andric return; 1480b57cec5SDimitry Andric case VK_DTPREL: 1490b57cec5SDimitry Andric case VK_GOTTPREL: 1500b57cec5SDimitry Andric case VK_TPREL: 1510b57cec5SDimitry Andric case VK_TLSDESC: 1520b57cec5SDimitry Andric break; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 1560b57cec5SDimitry Andric } 1575f757f3fSDimitry Andric 1585f757f3fSDimitry Andric const AArch64AuthMCExpr *AArch64AuthMCExpr::create(const MCExpr *Expr, 1595f757f3fSDimitry Andric uint16_t Discriminator, 1605f757f3fSDimitry Andric AArch64PACKey::ID Key, 1615f757f3fSDimitry Andric bool HasAddressDiversity, 1625f757f3fSDimitry Andric MCContext &Ctx) { 1635f757f3fSDimitry Andric return new (Ctx) 1645f757f3fSDimitry Andric AArch64AuthMCExpr(Expr, Discriminator, Key, HasAddressDiversity); 1655f757f3fSDimitry Andric } 1665f757f3fSDimitry Andric 1675f757f3fSDimitry Andric void AArch64AuthMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 1685f757f3fSDimitry Andric bool WrapSubExprInParens = !isa<MCSymbolRefExpr>(getSubExpr()); 1695f757f3fSDimitry Andric if (WrapSubExprInParens) 1705f757f3fSDimitry Andric OS << '('; 1715f757f3fSDimitry Andric getSubExpr()->print(OS, MAI); 1725f757f3fSDimitry Andric if (WrapSubExprInParens) 1735f757f3fSDimitry Andric OS << ')'; 1745f757f3fSDimitry Andric 1755f757f3fSDimitry Andric OS << "@AUTH(" << AArch64PACKeyIDToString(Key) << ',' << Discriminator; 1765f757f3fSDimitry Andric if (hasAddressDiversity()) 1775f757f3fSDimitry Andric OS << ",addr"; 1785f757f3fSDimitry Andric OS << ')'; 1795f757f3fSDimitry Andric } 1805f757f3fSDimitry Andric 1815f757f3fSDimitry Andric void AArch64AuthMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 1825f757f3fSDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 1835f757f3fSDimitry Andric } 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric MCFragment *AArch64AuthMCExpr::findAssociatedFragment() const { 1865f757f3fSDimitry Andric llvm_unreachable("FIXME: what goes here?"); 1875f757f3fSDimitry Andric } 1885f757f3fSDimitry Andric 1895f757f3fSDimitry Andric bool AArch64AuthMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 190*0fca6ea1SDimitry Andric const MCAssembler *Asm, 1915f757f3fSDimitry Andric const MCFixup *Fixup) const { 192*0fca6ea1SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup)) 1935f757f3fSDimitry Andric return false; 1945f757f3fSDimitry Andric 1955f757f3fSDimitry Andric if (Res.getSymB()) 1965f757f3fSDimitry Andric report_fatal_error("Auth relocation can't reference two symbols"); 1975f757f3fSDimitry Andric 1985f757f3fSDimitry Andric Res = MCValue::get(Res.getSymA(), nullptr, Res.getConstant(), getKind()); 1995f757f3fSDimitry Andric return true; 2005f757f3fSDimitry Andric } 201