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