1bdd1243dSDimitry Andric //===-- LoongArchMCExpr.cpp - LoongArch specific MC expression classes ----===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // This file contains the implementation of the assembly expression modifiers 10bdd1243dSDimitry Andric // accepted by the LoongArch architecture. 11bdd1243dSDimitry Andric // 12bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 13bdd1243dSDimitry Andric 14bdd1243dSDimitry Andric #include "LoongArchMCExpr.h" 15bdd1243dSDimitry Andric #include "LoongArchAsmBackend.h" 16bdd1243dSDimitry Andric #include "LoongArchFixupKinds.h" 17bdd1243dSDimitry Andric #include "llvm/MC/MCContext.h" 18bdd1243dSDimitry Andric #include "llvm/MC/MCStreamer.h" 19bdd1243dSDimitry Andric #include "llvm/MC/MCSymbolELF.h" 20bdd1243dSDimitry Andric #include "llvm/MC/MCValue.h" 21bdd1243dSDimitry Andric #include "llvm/Support/Casting.h" 22bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h" 23bdd1243dSDimitry Andric 24bdd1243dSDimitry Andric using namespace llvm; 25bdd1243dSDimitry Andric 26bdd1243dSDimitry Andric #define DEBUG_TYPE "loongarch-mcexpr" 27bdd1243dSDimitry Andric 28647cbc5dSDimitry Andric const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr, 29647cbc5dSDimitry Andric VariantKind Kind, MCContext &Ctx, 30647cbc5dSDimitry Andric bool Hint) { 31647cbc5dSDimitry Andric return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint); 32bdd1243dSDimitry Andric } 33bdd1243dSDimitry Andric 34bdd1243dSDimitry Andric void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 35bdd1243dSDimitry Andric VariantKind Kind = getKind(); 36bdd1243dSDimitry Andric bool HasVariant = 37bdd1243dSDimitry Andric ((Kind != VK_LoongArch_None) && (Kind != VK_LoongArch_CALL)); 38bdd1243dSDimitry Andric 39bdd1243dSDimitry Andric if (HasVariant) 40bdd1243dSDimitry Andric OS << '%' << getVariantKindName(getKind()) << '('; 41bdd1243dSDimitry Andric Expr->print(OS, MAI); 42bdd1243dSDimitry Andric if (HasVariant) 43bdd1243dSDimitry Andric OS << ')'; 44bdd1243dSDimitry Andric } 45bdd1243dSDimitry Andric 46bdd1243dSDimitry Andric bool LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 470fca6ea1SDimitry Andric const MCAssembler *Asm, 48bdd1243dSDimitry Andric const MCFixup *Fixup) const { 49bdd1243dSDimitry Andric // Explicitly drop the layout and assembler to prevent any symbolic folding in 50bdd1243dSDimitry Andric // the expression handling. This is required to preserve symbolic difference 51bdd1243dSDimitry Andric // expressions to emit the paired relocations. 52bdd1243dSDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) 53bdd1243dSDimitry Andric return false; 54bdd1243dSDimitry Andric 55bdd1243dSDimitry Andric Res = 56bdd1243dSDimitry Andric MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); 57bdd1243dSDimitry Andric // Custom fixup types are not valid with symbol difference expressions. 58bdd1243dSDimitry Andric return Res.getSymB() ? getKind() == VK_LoongArch_None : true; 59bdd1243dSDimitry Andric } 60bdd1243dSDimitry Andric 61bdd1243dSDimitry Andric void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 62bdd1243dSDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 63bdd1243dSDimitry Andric } 64bdd1243dSDimitry Andric 65bdd1243dSDimitry Andric StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) { 66bdd1243dSDimitry Andric switch (Kind) { 67bdd1243dSDimitry Andric default: 68bdd1243dSDimitry Andric llvm_unreachable("Invalid ELF symbol kind"); 69bdd1243dSDimitry Andric case VK_LoongArch_CALL_PLT: 70bdd1243dSDimitry Andric return "plt"; 71bdd1243dSDimitry Andric case VK_LoongArch_B16: 72bdd1243dSDimitry Andric return "b16"; 73bdd1243dSDimitry Andric case VK_LoongArch_B21: 74bdd1243dSDimitry Andric return "b21"; 75bdd1243dSDimitry Andric case VK_LoongArch_B26: 760fca6ea1SDimitry Andric return "b26"; 77bdd1243dSDimitry Andric case VK_LoongArch_ABS_HI20: 78bdd1243dSDimitry Andric return "abs_hi20"; 79bdd1243dSDimitry Andric case VK_LoongArch_ABS_LO12: 80bdd1243dSDimitry Andric return "abs_lo12"; 81bdd1243dSDimitry Andric case VK_LoongArch_ABS64_LO20: 82bdd1243dSDimitry Andric return "abs64_lo20"; 83bdd1243dSDimitry Andric case VK_LoongArch_ABS64_HI12: 84bdd1243dSDimitry Andric return "abs64_hi12"; 85bdd1243dSDimitry Andric case VK_LoongArch_PCALA_HI20: 86bdd1243dSDimitry Andric return "pc_hi20"; 87bdd1243dSDimitry Andric case VK_LoongArch_PCALA_LO12: 88bdd1243dSDimitry Andric return "pc_lo12"; 89bdd1243dSDimitry Andric case VK_LoongArch_PCALA64_LO20: 90bdd1243dSDimitry Andric return "pc64_lo20"; 91bdd1243dSDimitry Andric case VK_LoongArch_PCALA64_HI12: 92bdd1243dSDimitry Andric return "pc64_hi12"; 93bdd1243dSDimitry Andric case VK_LoongArch_GOT_PC_HI20: 94bdd1243dSDimitry Andric return "got_pc_hi20"; 95bdd1243dSDimitry Andric case VK_LoongArch_GOT_PC_LO12: 96bdd1243dSDimitry Andric return "got_pc_lo12"; 97bdd1243dSDimitry Andric case VK_LoongArch_GOT64_PC_LO20: 98bdd1243dSDimitry Andric return "got64_pc_lo20"; 99bdd1243dSDimitry Andric case VK_LoongArch_GOT64_PC_HI12: 100bdd1243dSDimitry Andric return "got64_pc_hi12"; 101bdd1243dSDimitry Andric case VK_LoongArch_GOT_HI20: 102bdd1243dSDimitry Andric return "got_hi20"; 103bdd1243dSDimitry Andric case VK_LoongArch_GOT_LO12: 104bdd1243dSDimitry Andric return "got_lo12"; 105bdd1243dSDimitry Andric case VK_LoongArch_GOT64_LO20: 106bdd1243dSDimitry Andric return "got64_lo20"; 107bdd1243dSDimitry Andric case VK_LoongArch_GOT64_HI12: 108bdd1243dSDimitry Andric return "got64_hi12"; 109bdd1243dSDimitry Andric case VK_LoongArch_TLS_LE_HI20: 110bdd1243dSDimitry Andric return "le_hi20"; 111bdd1243dSDimitry Andric case VK_LoongArch_TLS_LE_LO12: 112bdd1243dSDimitry Andric return "le_lo12"; 113bdd1243dSDimitry Andric case VK_LoongArch_TLS_LE64_LO20: 114bdd1243dSDimitry Andric return "le64_lo20"; 115bdd1243dSDimitry Andric case VK_LoongArch_TLS_LE64_HI12: 116bdd1243dSDimitry Andric return "le64_hi12"; 117bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_PC_HI20: 118bdd1243dSDimitry Andric return "ie_pc_hi20"; 119bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_PC_LO12: 120bdd1243dSDimitry Andric return "ie_pc_lo12"; 121bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE64_PC_LO20: 122bdd1243dSDimitry Andric return "ie64_pc_lo20"; 123bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE64_PC_HI12: 124bdd1243dSDimitry Andric return "ie64_pc_hi12"; 125bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_HI20: 126bdd1243dSDimitry Andric return "ie_hi20"; 127bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_LO12: 128bdd1243dSDimitry Andric return "ie_lo12"; 129bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE64_LO20: 130bdd1243dSDimitry Andric return "ie64_lo20"; 131bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE64_HI12: 132bdd1243dSDimitry Andric return "ie64_hi12"; 133bdd1243dSDimitry Andric case VK_LoongArch_TLS_LD_PC_HI20: 134bdd1243dSDimitry Andric return "ld_pc_hi20"; 135bdd1243dSDimitry Andric case VK_LoongArch_TLS_LD_HI20: 136bdd1243dSDimitry Andric return "ld_hi20"; 137bdd1243dSDimitry Andric case VK_LoongArch_TLS_GD_PC_HI20: 138bdd1243dSDimitry Andric return "gd_pc_hi20"; 139bdd1243dSDimitry Andric case VK_LoongArch_TLS_GD_HI20: 140bdd1243dSDimitry Andric return "gd_hi20"; 1411db9f3b2SDimitry Andric case VK_LoongArch_CALL36: 1421db9f3b2SDimitry Andric return "call36"; 1430fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_PC_HI20: 1440fca6ea1SDimitry Andric return "desc_pc_hi20"; 1450fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_PC_LO12: 1460fca6ea1SDimitry Andric return "desc_pc_lo12"; 1470fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC64_PC_LO20: 1480fca6ea1SDimitry Andric return "desc64_pc_lo20"; 1490fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC64_PC_HI12: 1500fca6ea1SDimitry Andric return "desc64_pc_hi12"; 1510fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_HI20: 1520fca6ea1SDimitry Andric return "desc_hi20"; 1530fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_LO12: 1540fca6ea1SDimitry Andric return "desc_lo12"; 1550fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC64_LO20: 1560fca6ea1SDimitry Andric return "desc64_lo20"; 1570fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC64_HI12: 1580fca6ea1SDimitry Andric return "desc64_hi12"; 1590fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_LD: 1600fca6ea1SDimitry Andric return "desc_ld"; 1610fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_CALL: 1620fca6ea1SDimitry Andric return "desc_call"; 1630fca6ea1SDimitry Andric case VK_LoongArch_TLS_LE_HI20_R: 1640fca6ea1SDimitry Andric return "le_hi20_r"; 1650fca6ea1SDimitry Andric case VK_LoongArch_TLS_LE_ADD_R: 1660fca6ea1SDimitry Andric return "le_add_r"; 1670fca6ea1SDimitry Andric case VK_LoongArch_TLS_LE_LO12_R: 1680fca6ea1SDimitry Andric return "le_lo12_r"; 169*52418fc2SDimitry Andric case VK_LoongArch_PCREL20_S2: 170*52418fc2SDimitry Andric return "pcrel_20"; 171*52418fc2SDimitry Andric case VK_LoongArch_TLS_LD_PCREL20_S2: 172*52418fc2SDimitry Andric return "ld_pcrel_20"; 173*52418fc2SDimitry Andric case VK_LoongArch_TLS_GD_PCREL20_S2: 174*52418fc2SDimitry Andric return "gd_pcrel_20"; 175*52418fc2SDimitry Andric case VK_LoongArch_TLS_DESC_PCREL20_S2: 176*52418fc2SDimitry Andric return "desc_pcrel_20"; 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric } 179bdd1243dSDimitry Andric 180bdd1243dSDimitry Andric LoongArchMCExpr::VariantKind 181bdd1243dSDimitry Andric LoongArchMCExpr::getVariantKindForName(StringRef name) { 182bdd1243dSDimitry Andric return StringSwitch<LoongArchMCExpr::VariantKind>(name) 183bdd1243dSDimitry Andric .Case("plt", VK_LoongArch_CALL_PLT) 184bdd1243dSDimitry Andric .Case("b16", VK_LoongArch_B16) 185bdd1243dSDimitry Andric .Case("b21", VK_LoongArch_B21) 186bdd1243dSDimitry Andric .Case("b26", VK_LoongArch_B26) 187bdd1243dSDimitry Andric .Case("abs_hi20", VK_LoongArch_ABS_HI20) 188bdd1243dSDimitry Andric .Case("abs_lo12", VK_LoongArch_ABS_LO12) 189bdd1243dSDimitry Andric .Case("abs64_lo20", VK_LoongArch_ABS64_LO20) 190bdd1243dSDimitry Andric .Case("abs64_hi12", VK_LoongArch_ABS64_HI12) 191bdd1243dSDimitry Andric .Case("pc_hi20", VK_LoongArch_PCALA_HI20) 192bdd1243dSDimitry Andric .Case("pc_lo12", VK_LoongArch_PCALA_LO12) 193bdd1243dSDimitry Andric .Case("pc64_lo20", VK_LoongArch_PCALA64_LO20) 194bdd1243dSDimitry Andric .Case("pc64_hi12", VK_LoongArch_PCALA64_HI12) 195bdd1243dSDimitry Andric .Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20) 196bdd1243dSDimitry Andric .Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12) 197bdd1243dSDimitry Andric .Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20) 198bdd1243dSDimitry Andric .Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12) 199bdd1243dSDimitry Andric .Case("got_hi20", VK_LoongArch_GOT_HI20) 200bdd1243dSDimitry Andric .Case("got_lo12", VK_LoongArch_GOT_LO12) 201bdd1243dSDimitry Andric .Case("got64_lo20", VK_LoongArch_GOT64_LO20) 202bdd1243dSDimitry Andric .Case("got64_hi12", VK_LoongArch_GOT64_HI12) 203bdd1243dSDimitry Andric .Case("le_hi20", VK_LoongArch_TLS_LE_HI20) 204bdd1243dSDimitry Andric .Case("le_lo12", VK_LoongArch_TLS_LE_LO12) 205bdd1243dSDimitry Andric .Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20) 206bdd1243dSDimitry Andric .Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12) 207bdd1243dSDimitry Andric .Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20) 208bdd1243dSDimitry Andric .Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12) 209bdd1243dSDimitry Andric .Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20) 210bdd1243dSDimitry Andric .Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12) 211bdd1243dSDimitry Andric .Case("ie_hi20", VK_LoongArch_TLS_IE_HI20) 212bdd1243dSDimitry Andric .Case("ie_lo12", VK_LoongArch_TLS_IE_LO12) 213bdd1243dSDimitry Andric .Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20) 214bdd1243dSDimitry Andric .Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12) 215bdd1243dSDimitry Andric .Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20) 216bdd1243dSDimitry Andric .Case("ld_hi20", VK_LoongArch_TLS_LD_HI20) 217bdd1243dSDimitry Andric .Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20) 218bdd1243dSDimitry Andric .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20) 2191db9f3b2SDimitry Andric .Case("call36", VK_LoongArch_CALL36) 2200fca6ea1SDimitry Andric .Case("desc_pc_hi20", VK_LoongArch_TLS_DESC_PC_HI20) 2210fca6ea1SDimitry Andric .Case("desc_pc_lo12", VK_LoongArch_TLS_DESC_PC_LO12) 2220fca6ea1SDimitry Andric .Case("desc64_pc_lo20", VK_LoongArch_TLS_DESC64_PC_LO20) 2230fca6ea1SDimitry Andric .Case("desc64_pc_hi12", VK_LoongArch_TLS_DESC64_PC_HI12) 2240fca6ea1SDimitry Andric .Case("desc_hi20", VK_LoongArch_TLS_DESC_HI20) 2250fca6ea1SDimitry Andric .Case("desc_lo12", VK_LoongArch_TLS_DESC_LO12) 2260fca6ea1SDimitry Andric .Case("desc64_lo20", VK_LoongArch_TLS_DESC64_LO20) 2270fca6ea1SDimitry Andric .Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12) 2280fca6ea1SDimitry Andric .Case("desc_ld", VK_LoongArch_TLS_DESC_LD) 2290fca6ea1SDimitry Andric .Case("desc_call", VK_LoongArch_TLS_DESC_CALL) 2300fca6ea1SDimitry Andric .Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R) 2310fca6ea1SDimitry Andric .Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R) 2320fca6ea1SDimitry Andric .Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R) 233*52418fc2SDimitry Andric .Case("pcrel_20", VK_LoongArch_PCREL20_S2) 234*52418fc2SDimitry Andric .Case("ld_pcrel_20", VK_LoongArch_TLS_LD_PCREL20_S2) 235*52418fc2SDimitry Andric .Case("gd_pcrel_20", VK_LoongArch_TLS_GD_PCREL20_S2) 236*52418fc2SDimitry Andric .Case("desc_pcrel_20", VK_LoongArch_TLS_DESC_PCREL20_S2) 237bdd1243dSDimitry Andric .Default(VK_LoongArch_Invalid); 238bdd1243dSDimitry Andric } 239bdd1243dSDimitry Andric 240bdd1243dSDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 241bdd1243dSDimitry Andric switch (Expr->getKind()) { 242bdd1243dSDimitry Andric case MCExpr::Target: 243bdd1243dSDimitry Andric llvm_unreachable("Can't handle nested target expression"); 244bdd1243dSDimitry Andric break; 245bdd1243dSDimitry Andric case MCExpr::Constant: 246bdd1243dSDimitry Andric break; 247bdd1243dSDimitry Andric case MCExpr::Unary: 248bdd1243dSDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 249bdd1243dSDimitry Andric break; 250bdd1243dSDimitry Andric case MCExpr::Binary: { 251bdd1243dSDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 252bdd1243dSDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 253bdd1243dSDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 254bdd1243dSDimitry Andric break; 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric case MCExpr::SymbolRef: { 257bdd1243dSDimitry Andric // We're known to be under a TLS fixup, so any symbol should be 258bdd1243dSDimitry Andric // modified. There should be only one. 259bdd1243dSDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 260bdd1243dSDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 261bdd1243dSDimitry Andric break; 262bdd1243dSDimitry Andric } 263bdd1243dSDimitry Andric } 264bdd1243dSDimitry Andric } 265bdd1243dSDimitry Andric 266bdd1243dSDimitry Andric void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 267bdd1243dSDimitry Andric switch (getKind()) { 268bdd1243dSDimitry Andric default: 269bdd1243dSDimitry Andric return; 270bdd1243dSDimitry Andric case VK_LoongArch_TLS_LE_HI20: 271bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_PC_HI20: 272bdd1243dSDimitry Andric case VK_LoongArch_TLS_IE_HI20: 273bdd1243dSDimitry Andric case VK_LoongArch_TLS_LD_PC_HI20: 274bdd1243dSDimitry Andric case VK_LoongArch_TLS_LD_HI20: 275bdd1243dSDimitry Andric case VK_LoongArch_TLS_GD_PC_HI20: 276bdd1243dSDimitry Andric case VK_LoongArch_TLS_GD_HI20: 2770fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_PC_HI20: 2780fca6ea1SDimitry Andric case VK_LoongArch_TLS_DESC_HI20: 279*52418fc2SDimitry Andric case VK_LoongArch_TLS_LD_PCREL20_S2: 280*52418fc2SDimitry Andric case VK_LoongArch_TLS_GD_PCREL20_S2: 281*52418fc2SDimitry Andric case VK_LoongArch_TLS_DESC_PCREL20_S2: 282bdd1243dSDimitry Andric break; 283bdd1243dSDimitry Andric } 284bdd1243dSDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 285bdd1243dSDimitry Andric } 286