10b57cec5SDimitry Andric //=--- AArch64MCExpr.h - AArch64 specific MC expression classes ---*- C++ -*-=// 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 describes AArch64-specific MCExprs, used for modifiers like 100b57cec5SDimitry Andric // ":lo12:" or ":gottprel_g1:". 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCEXPR_H 150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCEXPR_H 160b57cec5SDimitry Andric 175f757f3fSDimitry Andric #include "Utils/AArch64BaseInfo.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 195f757f3fSDimitry Andric #include "llvm/Support/Casting.h" 200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric class AArch64MCExpr : public MCTargetExpr { 250b57cec5SDimitry Andric public: 260b57cec5SDimitry Andric enum VariantKind { 270b57cec5SDimitry Andric // Symbol locations specifying (roughly speaking) what calculation should be 280b57cec5SDimitry Andric // performed to construct the final address for the relocated 290b57cec5SDimitry Andric // symbol. E.g. direct, via the GOT, ... 300b57cec5SDimitry Andric VK_ABS = 0x001, 310b57cec5SDimitry Andric VK_SABS = 0x002, 328bcb0991SDimitry Andric VK_PREL = 0x003, 338bcb0991SDimitry Andric VK_GOT = 0x004, 348bcb0991SDimitry Andric VK_DTPREL = 0x005, 358bcb0991SDimitry Andric VK_GOTTPREL = 0x006, 368bcb0991SDimitry Andric VK_TPREL = 0x007, 378bcb0991SDimitry Andric VK_TLSDESC = 0x008, 388bcb0991SDimitry Andric VK_SECREL = 0x009, 395f757f3fSDimitry Andric VK_AUTH = 0x00a, 405f757f3fSDimitry Andric VK_AUTHADDR = 0x00b, 410b57cec5SDimitry Andric VK_SymLocBits = 0x00f, 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric // Variants specifying which part of the final address calculation is 440b57cec5SDimitry Andric // used. E.g. the low 12 bits for an ADD/LDR, the middle 16 bits for a 450b57cec5SDimitry Andric // MOVZ/MOVK. 460b57cec5SDimitry Andric VK_PAGE = 0x010, 470b57cec5SDimitry Andric VK_PAGEOFF = 0x020, 480b57cec5SDimitry Andric VK_HI12 = 0x030, 490b57cec5SDimitry Andric VK_G0 = 0x040, 500b57cec5SDimitry Andric VK_G1 = 0x050, 510b57cec5SDimitry Andric VK_G2 = 0x060, 520b57cec5SDimitry Andric VK_G3 = 0x070, 53e8d8bef9SDimitry Andric VK_LO15 = 0x080, 540b57cec5SDimitry Andric VK_AddressFragBits = 0x0f0, 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // Whether the final relocation is a checked one (where a linker should 570b57cec5SDimitry Andric // perform a range-check on the final address) or not. Note that this field 580b57cec5SDimitry Andric // is unfortunately sometimes omitted from the assembly syntax. E.g. :lo12: 590b57cec5SDimitry Andric // on its own is a non-checked relocation. We side with ELF on being 600b57cec5SDimitry Andric // explicit about this! 610b57cec5SDimitry Andric VK_NC = 0x100, 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Convenience definitions for referring to specific textual representations 640b57cec5SDimitry Andric // of relocation specifiers. Note that this means the "_NC" is sometimes 650b57cec5SDimitry Andric // omitted in line with assembly syntax here (VK_LO12 rather than VK_LO12_NC 660b57cec5SDimitry Andric // since a user would write ":lo12:"). 670b57cec5SDimitry Andric VK_CALL = VK_ABS, 680b57cec5SDimitry Andric VK_ABS_PAGE = VK_ABS | VK_PAGE, 690b57cec5SDimitry Andric VK_ABS_PAGE_NC = VK_ABS | VK_PAGE | VK_NC, 700b57cec5SDimitry Andric VK_ABS_G3 = VK_ABS | VK_G3, 710b57cec5SDimitry Andric VK_ABS_G2 = VK_ABS | VK_G2, 720b57cec5SDimitry Andric VK_ABS_G2_S = VK_SABS | VK_G2, 730b57cec5SDimitry Andric VK_ABS_G2_NC = VK_ABS | VK_G2 | VK_NC, 740b57cec5SDimitry Andric VK_ABS_G1 = VK_ABS | VK_G1, 750b57cec5SDimitry Andric VK_ABS_G1_S = VK_SABS | VK_G1, 760b57cec5SDimitry Andric VK_ABS_G1_NC = VK_ABS | VK_G1 | VK_NC, 770b57cec5SDimitry Andric VK_ABS_G0 = VK_ABS | VK_G0, 780b57cec5SDimitry Andric VK_ABS_G0_S = VK_SABS | VK_G0, 790b57cec5SDimitry Andric VK_ABS_G0_NC = VK_ABS | VK_G0 | VK_NC, 800b57cec5SDimitry Andric VK_LO12 = VK_ABS | VK_PAGEOFF | VK_NC, 818bcb0991SDimitry Andric VK_PREL_G3 = VK_PREL | VK_G3, 828bcb0991SDimitry Andric VK_PREL_G2 = VK_PREL | VK_G2, 838bcb0991SDimitry Andric VK_PREL_G2_NC = VK_PREL | VK_G2 | VK_NC, 848bcb0991SDimitry Andric VK_PREL_G1 = VK_PREL | VK_G1, 858bcb0991SDimitry Andric VK_PREL_G1_NC = VK_PREL | VK_G1 | VK_NC, 868bcb0991SDimitry Andric VK_PREL_G0 = VK_PREL | VK_G0, 878bcb0991SDimitry Andric VK_PREL_G0_NC = VK_PREL | VK_G0 | VK_NC, 880b57cec5SDimitry Andric VK_GOT_LO12 = VK_GOT | VK_PAGEOFF | VK_NC, 890b57cec5SDimitry Andric VK_GOT_PAGE = VK_GOT | VK_PAGE, 90e8d8bef9SDimitry Andric VK_GOT_PAGE_LO15 = VK_GOT | VK_LO15 | VK_NC, 910b57cec5SDimitry Andric VK_DTPREL_G2 = VK_DTPREL | VK_G2, 920b57cec5SDimitry Andric VK_DTPREL_G1 = VK_DTPREL | VK_G1, 930b57cec5SDimitry Andric VK_DTPREL_G1_NC = VK_DTPREL | VK_G1 | VK_NC, 940b57cec5SDimitry Andric VK_DTPREL_G0 = VK_DTPREL | VK_G0, 950b57cec5SDimitry Andric VK_DTPREL_G0_NC = VK_DTPREL | VK_G0 | VK_NC, 960b57cec5SDimitry Andric VK_DTPREL_HI12 = VK_DTPREL | VK_HI12, 970b57cec5SDimitry Andric VK_DTPREL_LO12 = VK_DTPREL | VK_PAGEOFF, 980b57cec5SDimitry Andric VK_DTPREL_LO12_NC = VK_DTPREL | VK_PAGEOFF | VK_NC, 990b57cec5SDimitry Andric VK_GOTTPREL_PAGE = VK_GOTTPREL | VK_PAGE, 1000b57cec5SDimitry Andric VK_GOTTPREL_LO12_NC = VK_GOTTPREL | VK_PAGEOFF | VK_NC, 1010b57cec5SDimitry Andric VK_GOTTPREL_G1 = VK_GOTTPREL | VK_G1, 1020b57cec5SDimitry Andric VK_GOTTPREL_G0_NC = VK_GOTTPREL | VK_G0 | VK_NC, 1030b57cec5SDimitry Andric VK_TPREL_G2 = VK_TPREL | VK_G2, 1040b57cec5SDimitry Andric VK_TPREL_G1 = VK_TPREL | VK_G1, 1050b57cec5SDimitry Andric VK_TPREL_G1_NC = VK_TPREL | VK_G1 | VK_NC, 1060b57cec5SDimitry Andric VK_TPREL_G0 = VK_TPREL | VK_G0, 1070b57cec5SDimitry Andric VK_TPREL_G0_NC = VK_TPREL | VK_G0 | VK_NC, 1080b57cec5SDimitry Andric VK_TPREL_HI12 = VK_TPREL | VK_HI12, 1090b57cec5SDimitry Andric VK_TPREL_LO12 = VK_TPREL | VK_PAGEOFF, 1100b57cec5SDimitry Andric VK_TPREL_LO12_NC = VK_TPREL | VK_PAGEOFF | VK_NC, 1110b57cec5SDimitry Andric VK_TLSDESC_LO12 = VK_TLSDESC | VK_PAGEOFF, 1120b57cec5SDimitry Andric VK_TLSDESC_PAGE = VK_TLSDESC | VK_PAGE, 1130b57cec5SDimitry Andric VK_SECREL_LO12 = VK_SECREL | VK_PAGEOFF, 1140b57cec5SDimitry Andric VK_SECREL_HI12 = VK_SECREL | VK_HI12, 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric VK_INVALID = 0xfff 1170b57cec5SDimitry Andric }; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric private: 1200b57cec5SDimitry Andric const MCExpr *Expr; 1210b57cec5SDimitry Andric const VariantKind Kind; 1220b57cec5SDimitry Andric 1235f757f3fSDimitry Andric protected: AArch64MCExpr(const MCExpr * Expr,VariantKind Kind)1240b57cec5SDimitry Andric explicit AArch64MCExpr(const MCExpr *Expr, VariantKind Kind) 1250b57cec5SDimitry Andric : Expr(Expr), Kind(Kind) {} 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric public: 1280b57cec5SDimitry Andric /// @name Construction 1290b57cec5SDimitry Andric /// @{ 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric static const AArch64MCExpr *create(const MCExpr *Expr, VariantKind Kind, 1320b57cec5SDimitry Andric MCContext &Ctx); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric /// @} 1350b57cec5SDimitry Andric /// @name Accessors 1360b57cec5SDimitry Andric /// @{ 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// Get the kind of this expression. getKind()1390b57cec5SDimitry Andric VariantKind getKind() const { return Kind; } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric /// Get the expression this modifier applies to. getSubExpr()1420b57cec5SDimitry Andric const MCExpr *getSubExpr() const { return Expr; } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /// @} 1450b57cec5SDimitry Andric /// @name VariantKind information extractors. 1460b57cec5SDimitry Andric /// @{ 1470b57cec5SDimitry Andric getSymbolLoc(VariantKind Kind)1480b57cec5SDimitry Andric static VariantKind getSymbolLoc(VariantKind Kind) { 1490b57cec5SDimitry Andric return static_cast<VariantKind>(Kind & VK_SymLocBits); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric getAddressFrag(VariantKind Kind)1520b57cec5SDimitry Andric static VariantKind getAddressFrag(VariantKind Kind) { 1530b57cec5SDimitry Andric return static_cast<VariantKind>(Kind & VK_AddressFragBits); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric isNotChecked(VariantKind Kind)1560b57cec5SDimitry Andric static bool isNotChecked(VariantKind Kind) { return Kind & VK_NC; } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// @} 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// Convert the variant kind into an ELF-appropriate modifier 1610b57cec5SDimitry Andric /// (e.g. ":got:", ":lo12:"). 1620b57cec5SDimitry Andric StringRef getVariantKindName() const; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric void visitUsedExpr(MCStreamer &Streamer) const override; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric MCFragment *findAssociatedFragment() const override; 1690b57cec5SDimitry Andric 170*0fca6ea1SDimitry Andric bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 1710b57cec5SDimitry Andric const MCFixup *Fixup) const override; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; 1740b57cec5SDimitry Andric classof(const MCExpr * E)1750b57cec5SDimitry Andric static bool classof(const MCExpr *E) { 1760b57cec5SDimitry Andric return E->getKind() == MCExpr::Target; 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric }; 1795f757f3fSDimitry Andric 1805f757f3fSDimitry Andric class AArch64AuthMCExpr final : public AArch64MCExpr { 1815f757f3fSDimitry Andric uint16_t Discriminator; 1825f757f3fSDimitry Andric AArch64PACKey::ID Key; 1835f757f3fSDimitry Andric AArch64AuthMCExpr(const MCExpr * Expr,uint16_t Discriminator,AArch64PACKey::ID Key,bool HasAddressDiversity)1845f757f3fSDimitry Andric explicit AArch64AuthMCExpr(const MCExpr *Expr, uint16_t Discriminator, 1855f757f3fSDimitry Andric AArch64PACKey::ID Key, bool HasAddressDiversity) 1865f757f3fSDimitry Andric : AArch64MCExpr(Expr, HasAddressDiversity ? VK_AUTHADDR : VK_AUTH), 1875f757f3fSDimitry Andric Discriminator(Discriminator), Key(Key) {} 1885f757f3fSDimitry Andric 1895f757f3fSDimitry Andric public: 1905f757f3fSDimitry Andric static const AArch64AuthMCExpr * 1915f757f3fSDimitry Andric create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, 1925f757f3fSDimitry Andric bool HasAddressDiversity, MCContext &Ctx); 1935f757f3fSDimitry Andric getKey()1945f757f3fSDimitry Andric AArch64PACKey::ID getKey() const { return Key; } getDiscriminator()1955f757f3fSDimitry Andric uint16_t getDiscriminator() const { return Discriminator; } hasAddressDiversity()1965f757f3fSDimitry Andric bool hasAddressDiversity() const { return getKind() == VK_AUTHADDR; } 1975f757f3fSDimitry Andric 1985f757f3fSDimitry Andric void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; 1995f757f3fSDimitry Andric 2005f757f3fSDimitry Andric void visitUsedExpr(MCStreamer &Streamer) const override; 2015f757f3fSDimitry Andric 2025f757f3fSDimitry Andric MCFragment *findAssociatedFragment() const override; 2035f757f3fSDimitry Andric 204*0fca6ea1SDimitry Andric bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 2055f757f3fSDimitry Andric const MCFixup *Fixup) const override; 2065f757f3fSDimitry Andric classof(const MCExpr * E)2075f757f3fSDimitry Andric static bool classof(const MCExpr *E) { 2085f757f3fSDimitry Andric return isa<AArch64MCExpr>(E) && classof(cast<AArch64MCExpr>(E)); 2095f757f3fSDimitry Andric } 2105f757f3fSDimitry Andric classof(const AArch64MCExpr * E)2115f757f3fSDimitry Andric static bool classof(const AArch64MCExpr *E) { 2125f757f3fSDimitry Andric return E->getKind() == VK_AUTH || E->getKind() == VK_AUTHADDR; 2135f757f3fSDimitry Andric } 2145f757f3fSDimitry Andric }; 2150b57cec5SDimitry Andric } // end namespace llvm 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric #endif 218