1c2ee21cfSwanglei //===-- LoongArchMCExpr.cpp - LoongArch specific MC expression classes ----===// 2c2ee21cfSwanglei // 3c2ee21cfSwanglei // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c2ee21cfSwanglei // See https://llvm.org/LICENSE.txt for license information. 5c2ee21cfSwanglei // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c2ee21cfSwanglei // 7c2ee21cfSwanglei //===----------------------------------------------------------------------===// 8c2ee21cfSwanglei // 9c2ee21cfSwanglei // This file contains the implementation of the assembly expression modifiers 10c2ee21cfSwanglei // accepted by the LoongArch architecture. 11c2ee21cfSwanglei // 12c2ee21cfSwanglei //===----------------------------------------------------------------------===// 13c2ee21cfSwanglei 14c2ee21cfSwanglei #include "LoongArchMCExpr.h" 15c2ee21cfSwanglei #include "LoongArchAsmBackend.h" 16c2ee21cfSwanglei #include "llvm/MC/MCContext.h" 17c2ee21cfSwanglei #include "llvm/MC/MCStreamer.h" 1839b1fec1Swanglei #include "llvm/MC/MCSymbolELF.h" 19c2ee21cfSwanglei #include "llvm/MC/MCValue.h" 2039b1fec1Swanglei #include "llvm/Support/Casting.h" 21c2ee21cfSwanglei #include "llvm/Support/ErrorHandling.h" 22c2ee21cfSwanglei 23c2ee21cfSwanglei using namespace llvm; 24c2ee21cfSwanglei 25c2ee21cfSwanglei #define DEBUG_TYPE "loongarch-mcexpr" 26c2ee21cfSwanglei 27b3ef8dceSJinyang He const LoongArchMCExpr *LoongArchMCExpr::create(const MCExpr *Expr, 28b3ef8dceSJinyang He VariantKind Kind, MCContext &Ctx, 29b3ef8dceSJinyang He bool Hint) { 30b3ef8dceSJinyang He return new (Ctx) LoongArchMCExpr(Expr, Kind, Hint); 31c2ee21cfSwanglei } 32c2ee21cfSwanglei 33c2ee21cfSwanglei void LoongArchMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 34c2ee21cfSwanglei VariantKind Kind = getKind(); 35c2ee21cfSwanglei bool HasVariant = 36c2ee21cfSwanglei ((Kind != VK_LoongArch_None) && (Kind != VK_LoongArch_CALL)); 37c2ee21cfSwanglei 38c2ee21cfSwanglei if (HasVariant) 39c2ee21cfSwanglei OS << '%' << getVariantKindName(getKind()) << '('; 40c2ee21cfSwanglei Expr->print(OS, MAI); 41c2ee21cfSwanglei if (HasVariant) 42c2ee21cfSwanglei OS << ')'; 43c2ee21cfSwanglei } 44c2ee21cfSwanglei 45c2ee21cfSwanglei bool LoongArchMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 46e25e8003SFangrui Song const MCAssembler *Asm, 47c2ee21cfSwanglei const MCFixup *Fixup) const { 48c2ee21cfSwanglei // Explicitly drop the layout and assembler to prevent any symbolic folding in 49c2ee21cfSwanglei // the expression handling. This is required to preserve symbolic difference 50c2ee21cfSwanglei // expressions to emit the paired relocations. 51c2ee21cfSwanglei if (!getSubExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) 52c2ee21cfSwanglei return false; 53c2ee21cfSwanglei 54c2ee21cfSwanglei Res = 55c2ee21cfSwanglei MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); 56c2ee21cfSwanglei // Custom fixup types are not valid with symbol difference expressions. 57c2ee21cfSwanglei return Res.getSymB() ? getKind() == VK_LoongArch_None : true; 58c2ee21cfSwanglei } 59c2ee21cfSwanglei 60c2ee21cfSwanglei void LoongArchMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 61c2ee21cfSwanglei Streamer.visitUsedExpr(*getSubExpr()); 62c2ee21cfSwanglei } 63c2ee21cfSwanglei 64c2ee21cfSwanglei StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) { 65c2ee21cfSwanglei switch (Kind) { 66c2ee21cfSwanglei default: 67c2ee21cfSwanglei llvm_unreachable("Invalid ELF symbol kind"); 68c2ee21cfSwanglei case VK_LoongArch_CALL_PLT: 69c2ee21cfSwanglei return "plt"; 70bf479547Swanglei case VK_LoongArch_B16: 71bf479547Swanglei return "b16"; 72bf479547Swanglei case VK_LoongArch_B21: 73bf479547Swanglei return "b21"; 74bf479547Swanglei case VK_LoongArch_B26: 7507dfa61aSZhaoQi return "b26"; 76bf479547Swanglei case VK_LoongArch_ABS_HI20: 77bf479547Swanglei return "abs_hi20"; 78bf479547Swanglei case VK_LoongArch_ABS_LO12: 79bf479547Swanglei return "abs_lo12"; 80bf479547Swanglei case VK_LoongArch_ABS64_LO20: 81bf479547Swanglei return "abs64_lo20"; 82bf479547Swanglei case VK_LoongArch_ABS64_HI12: 83bf479547Swanglei return "abs64_hi12"; 84bf479547Swanglei case VK_LoongArch_PCALA_HI20: 85c2ee21cfSwanglei return "pc_hi20"; 86bf479547Swanglei case VK_LoongArch_PCALA_LO12: 87c2ee21cfSwanglei return "pc_lo12"; 88bf479547Swanglei case VK_LoongArch_PCALA64_LO20: 89bf479547Swanglei return "pc64_lo20"; 90bf479547Swanglei case VK_LoongArch_PCALA64_HI12: 91bf479547Swanglei return "pc64_hi12"; 92bf479547Swanglei case VK_LoongArch_GOT_PC_HI20: 93bf479547Swanglei return "got_pc_hi20"; 94bf479547Swanglei case VK_LoongArch_GOT_PC_LO12: 95bf479547Swanglei return "got_pc_lo12"; 96bf479547Swanglei case VK_LoongArch_GOT64_PC_LO20: 97bf479547Swanglei return "got64_pc_lo20"; 98bf479547Swanglei case VK_LoongArch_GOT64_PC_HI12: 99bf479547Swanglei return "got64_pc_hi12"; 100bf479547Swanglei case VK_LoongArch_GOT_HI20: 101bf479547Swanglei return "got_hi20"; 102bf479547Swanglei case VK_LoongArch_GOT_LO12: 103bf479547Swanglei return "got_lo12"; 104bf479547Swanglei case VK_LoongArch_GOT64_LO20: 105bf479547Swanglei return "got64_lo20"; 106bf479547Swanglei case VK_LoongArch_GOT64_HI12: 107bf479547Swanglei return "got64_hi12"; 108bf479547Swanglei case VK_LoongArch_TLS_LE_HI20: 109bf479547Swanglei return "le_hi20"; 110bf479547Swanglei case VK_LoongArch_TLS_LE_LO12: 111bf479547Swanglei return "le_lo12"; 112bf479547Swanglei case VK_LoongArch_TLS_LE64_LO20: 113bf479547Swanglei return "le64_lo20"; 114bf479547Swanglei case VK_LoongArch_TLS_LE64_HI12: 115bf479547Swanglei return "le64_hi12"; 116bf479547Swanglei case VK_LoongArch_TLS_IE_PC_HI20: 117bf479547Swanglei return "ie_pc_hi20"; 118bf479547Swanglei case VK_LoongArch_TLS_IE_PC_LO12: 119bf479547Swanglei return "ie_pc_lo12"; 120bf479547Swanglei case VK_LoongArch_TLS_IE64_PC_LO20: 121bf479547Swanglei return "ie64_pc_lo20"; 122bf479547Swanglei case VK_LoongArch_TLS_IE64_PC_HI12: 123bf479547Swanglei return "ie64_pc_hi12"; 124bf479547Swanglei case VK_LoongArch_TLS_IE_HI20: 125bf479547Swanglei return "ie_hi20"; 126bf479547Swanglei case VK_LoongArch_TLS_IE_LO12: 127bf479547Swanglei return "ie_lo12"; 128bf479547Swanglei case VK_LoongArch_TLS_IE64_LO20: 129bf479547Swanglei return "ie64_lo20"; 130bf479547Swanglei case VK_LoongArch_TLS_IE64_HI12: 131bf479547Swanglei return "ie64_hi12"; 132bf479547Swanglei case VK_LoongArch_TLS_LD_PC_HI20: 133bf479547Swanglei return "ld_pc_hi20"; 134bf479547Swanglei case VK_LoongArch_TLS_LD_HI20: 135bf479547Swanglei return "ld_hi20"; 136bf479547Swanglei case VK_LoongArch_TLS_GD_PC_HI20: 137bf479547Swanglei return "gd_pc_hi20"; 138bf479547Swanglei case VK_LoongArch_TLS_GD_HI20: 139bf479547Swanglei return "gd_hi20"; 1402cf420d5Swanglei case VK_LoongArch_CALL36: 1412cf420d5Swanglei return "call36"; 1424a84d8e4Swanglei case VK_LoongArch_TLS_DESC_PC_HI20: 1434a84d8e4Swanglei return "desc_pc_hi20"; 1444a84d8e4Swanglei case VK_LoongArch_TLS_DESC_PC_LO12: 1454a84d8e4Swanglei return "desc_pc_lo12"; 1464a84d8e4Swanglei case VK_LoongArch_TLS_DESC64_PC_LO20: 1474a84d8e4Swanglei return "desc64_pc_lo20"; 1484a84d8e4Swanglei case VK_LoongArch_TLS_DESC64_PC_HI12: 1494a84d8e4Swanglei return "desc64_pc_hi12"; 1504a84d8e4Swanglei case VK_LoongArch_TLS_DESC_HI20: 1514a84d8e4Swanglei return "desc_hi20"; 1524a84d8e4Swanglei case VK_LoongArch_TLS_DESC_LO12: 1534a84d8e4Swanglei return "desc_lo12"; 1544a84d8e4Swanglei case VK_LoongArch_TLS_DESC64_LO20: 1554a84d8e4Swanglei return "desc64_lo20"; 1564a84d8e4Swanglei case VK_LoongArch_TLS_DESC64_HI12: 1574a84d8e4Swanglei return "desc64_hi12"; 1584a84d8e4Swanglei case VK_LoongArch_TLS_DESC_LD: 1594a84d8e4Swanglei return "desc_ld"; 1604a84d8e4Swanglei case VK_LoongArch_TLS_DESC_CALL: 1614a84d8e4Swanglei return "desc_call"; 1620f231567Swanglei case VK_LoongArch_TLS_LE_HI20_R: 1630f231567Swanglei return "le_hi20_r"; 1640f231567Swanglei case VK_LoongArch_TLS_LE_ADD_R: 1650f231567Swanglei return "le_add_r"; 1660f231567Swanglei case VK_LoongArch_TLS_LE_LO12_R: 1670f231567Swanglei return "le_lo12_r"; 168*e27358c8Swanglei case VK_LoongArch_PCREL20_S2: 169*e27358c8Swanglei return "pcrel_20"; 170*e27358c8Swanglei case VK_LoongArch_TLS_LD_PCREL20_S2: 171*e27358c8Swanglei return "ld_pcrel_20"; 172*e27358c8Swanglei case VK_LoongArch_TLS_GD_PCREL20_S2: 173*e27358c8Swanglei return "gd_pcrel_20"; 174*e27358c8Swanglei case VK_LoongArch_TLS_DESC_PCREL20_S2: 175*e27358c8Swanglei return "desc_pcrel_20"; 176c2ee21cfSwanglei } 177c2ee21cfSwanglei } 178c2ee21cfSwanglei 179c2ee21cfSwanglei LoongArchMCExpr::VariantKind 180c2ee21cfSwanglei LoongArchMCExpr::getVariantKindForName(StringRef name) { 181c2ee21cfSwanglei return StringSwitch<LoongArchMCExpr::VariantKind>(name) 182c2ee21cfSwanglei .Case("plt", VK_LoongArch_CALL_PLT) 183bf479547Swanglei .Case("b16", VK_LoongArch_B16) 184bf479547Swanglei .Case("b21", VK_LoongArch_B21) 185bf479547Swanglei .Case("b26", VK_LoongArch_B26) 186bf479547Swanglei .Case("abs_hi20", VK_LoongArch_ABS_HI20) 187bf479547Swanglei .Case("abs_lo12", VK_LoongArch_ABS_LO12) 188bf479547Swanglei .Case("abs64_lo20", VK_LoongArch_ABS64_LO20) 189bf479547Swanglei .Case("abs64_hi12", VK_LoongArch_ABS64_HI12) 190bf479547Swanglei .Case("pc_hi20", VK_LoongArch_PCALA_HI20) 191bf479547Swanglei .Case("pc_lo12", VK_LoongArch_PCALA_LO12) 192bf479547Swanglei .Case("pc64_lo20", VK_LoongArch_PCALA64_LO20) 193bf479547Swanglei .Case("pc64_hi12", VK_LoongArch_PCALA64_HI12) 194bf479547Swanglei .Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20) 195bf479547Swanglei .Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12) 196bf479547Swanglei .Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20) 197bf479547Swanglei .Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12) 198bf479547Swanglei .Case("got_hi20", VK_LoongArch_GOT_HI20) 199bf479547Swanglei .Case("got_lo12", VK_LoongArch_GOT_LO12) 200bf479547Swanglei .Case("got64_lo20", VK_LoongArch_GOT64_LO20) 201bf479547Swanglei .Case("got64_hi12", VK_LoongArch_GOT64_HI12) 202bf479547Swanglei .Case("le_hi20", VK_LoongArch_TLS_LE_HI20) 203bf479547Swanglei .Case("le_lo12", VK_LoongArch_TLS_LE_LO12) 204bf479547Swanglei .Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20) 205bf479547Swanglei .Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12) 206bf479547Swanglei .Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20) 207bf479547Swanglei .Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12) 208bf479547Swanglei .Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20) 209bf479547Swanglei .Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12) 210bf479547Swanglei .Case("ie_hi20", VK_LoongArch_TLS_IE_HI20) 211bf479547Swanglei .Case("ie_lo12", VK_LoongArch_TLS_IE_LO12) 212bf479547Swanglei .Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20) 213bf479547Swanglei .Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12) 214bf479547Swanglei .Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20) 215bf479547Swanglei .Case("ld_hi20", VK_LoongArch_TLS_LD_HI20) 216bf479547Swanglei .Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20) 217bf479547Swanglei .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20) 2182cf420d5Swanglei .Case("call36", VK_LoongArch_CALL36) 2194a84d8e4Swanglei .Case("desc_pc_hi20", VK_LoongArch_TLS_DESC_PC_HI20) 2204a84d8e4Swanglei .Case("desc_pc_lo12", VK_LoongArch_TLS_DESC_PC_LO12) 2214a84d8e4Swanglei .Case("desc64_pc_lo20", VK_LoongArch_TLS_DESC64_PC_LO20) 2224a84d8e4Swanglei .Case("desc64_pc_hi12", VK_LoongArch_TLS_DESC64_PC_HI12) 2234a84d8e4Swanglei .Case("desc_hi20", VK_LoongArch_TLS_DESC_HI20) 2244a84d8e4Swanglei .Case("desc_lo12", VK_LoongArch_TLS_DESC_LO12) 2254a84d8e4Swanglei .Case("desc64_lo20", VK_LoongArch_TLS_DESC64_LO20) 2264a84d8e4Swanglei .Case("desc64_hi12", VK_LoongArch_TLS_DESC64_HI12) 2274a84d8e4Swanglei .Case("desc_ld", VK_LoongArch_TLS_DESC_LD) 2284a84d8e4Swanglei .Case("desc_call", VK_LoongArch_TLS_DESC_CALL) 2290f231567Swanglei .Case("le_hi20_r", VK_LoongArch_TLS_LE_HI20_R) 2300f231567Swanglei .Case("le_add_r", VK_LoongArch_TLS_LE_ADD_R) 2310f231567Swanglei .Case("le_lo12_r", VK_LoongArch_TLS_LE_LO12_R) 232*e27358c8Swanglei .Case("pcrel_20", VK_LoongArch_PCREL20_S2) 233*e27358c8Swanglei .Case("ld_pcrel_20", VK_LoongArch_TLS_LD_PCREL20_S2) 234*e27358c8Swanglei .Case("gd_pcrel_20", VK_LoongArch_TLS_GD_PCREL20_S2) 235*e27358c8Swanglei .Case("desc_pcrel_20", VK_LoongArch_TLS_DESC_PCREL20_S2) 236c2ee21cfSwanglei .Default(VK_LoongArch_Invalid); 237c2ee21cfSwanglei } 23839b1fec1Swanglei 23939b1fec1Swanglei static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 24039b1fec1Swanglei switch (Expr->getKind()) { 24139b1fec1Swanglei case MCExpr::Target: 24239b1fec1Swanglei llvm_unreachable("Can't handle nested target expression"); 24339b1fec1Swanglei break; 24439b1fec1Swanglei case MCExpr::Constant: 24539b1fec1Swanglei break; 24639b1fec1Swanglei case MCExpr::Unary: 24739b1fec1Swanglei fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 24839b1fec1Swanglei break; 24939b1fec1Swanglei case MCExpr::Binary: { 25039b1fec1Swanglei const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 25139b1fec1Swanglei fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 25239b1fec1Swanglei fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 25339b1fec1Swanglei break; 25439b1fec1Swanglei } 25539b1fec1Swanglei case MCExpr::SymbolRef: { 25639b1fec1Swanglei // We're known to be under a TLS fixup, so any symbol should be 25739b1fec1Swanglei // modified. There should be only one. 25839b1fec1Swanglei const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 25939b1fec1Swanglei cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 26039b1fec1Swanglei break; 26139b1fec1Swanglei } 26239b1fec1Swanglei } 26339b1fec1Swanglei } 26439b1fec1Swanglei 26539b1fec1Swanglei void LoongArchMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 26639b1fec1Swanglei switch (getKind()) { 26739b1fec1Swanglei default: 26839b1fec1Swanglei return; 26939b1fec1Swanglei case VK_LoongArch_TLS_LE_HI20: 27039b1fec1Swanglei case VK_LoongArch_TLS_IE_PC_HI20: 27139b1fec1Swanglei case VK_LoongArch_TLS_IE_HI20: 27239b1fec1Swanglei case VK_LoongArch_TLS_LD_PC_HI20: 27339b1fec1Swanglei case VK_LoongArch_TLS_LD_HI20: 27439b1fec1Swanglei case VK_LoongArch_TLS_GD_PC_HI20: 27539b1fec1Swanglei case VK_LoongArch_TLS_GD_HI20: 2764a84d8e4Swanglei case VK_LoongArch_TLS_DESC_PC_HI20: 2774a84d8e4Swanglei case VK_LoongArch_TLS_DESC_HI20: 278*e27358c8Swanglei case VK_LoongArch_TLS_LD_PCREL20_S2: 279*e27358c8Swanglei case VK_LoongArch_TLS_GD_PCREL20_S2: 280*e27358c8Swanglei case VK_LoongArch_TLS_DESC_PCREL20_S2: 28139b1fec1Swanglei break; 28239b1fec1Swanglei } 28339b1fec1Swanglei fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 28439b1fec1Swanglei } 285