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