1 //===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===// 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 #include "CSKYMCExpr.h" 10 #include "CSKYFixupKinds.h" 11 #include "llvm/BinaryFormat/ELF.h" 12 #include "llvm/MC/MCAssembler.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCStreamer.h" 15 #include "llvm/MC/MCSymbolELF.h" 16 #include "llvm/Support/Casting.h" 17 18 using namespace llvm; 19 20 #define DEBUG_TYPE "csky-mc-expr" 21 22 const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind, 23 MCContext &Ctx) { 24 return new (Ctx) CSKYMCExpr(Kind, Expr); 25 } 26 27 StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) { 28 switch (Kind) { 29 default: 30 llvm_unreachable("Invalid ELF symbol kind"); 31 case VK_CSKY_None: 32 case VK_CSKY_ADDR: 33 return ""; 34 case VK_CSKY_ADDR_HI16: 35 return "@HI16"; 36 case VK_CSKY_ADDR_LO16: 37 return "@LO16"; 38 case VK_CSKY_GOT_IMM18_BY4: 39 case VK_CSKY_GOT: 40 return "@GOT"; 41 case VK_CSKY_GOTPC: 42 return "@GOTPC"; 43 case VK_CSKY_GOTOFF: 44 return "@GOTOFF"; 45 case VK_CSKY_PLT_IMM18_BY4: 46 case VK_CSKY_PLT: 47 return "@PLT"; 48 case VK_CSKY_TLSLE: 49 return "@TPOFF"; 50 case VK_CSKY_TLSIE: 51 return "@GOTTPOFF"; 52 case VK_CSKY_TLSGD: 53 return "@TLSGD32"; 54 case VK_CSKY_TLSLDO: 55 return "@TLSLDO32"; 56 case VK_CSKY_TLSLDM: 57 return "@TLSLDM32"; 58 } 59 } 60 61 void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 62 Streamer.visitUsedExpr(*getSubExpr()); 63 } 64 65 void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 66 Expr->print(OS, MAI); 67 OS << getVariantKindName(getKind()); 68 } 69 70 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 71 switch (Expr->getKind()) { 72 case MCExpr::Target: 73 llvm_unreachable("Can't handle nested target expression"); 74 break; 75 case MCExpr::Constant: 76 break; 77 78 case MCExpr::Binary: { 79 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 80 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 81 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 82 break; 83 } 84 85 case MCExpr::SymbolRef: { 86 // We're known to be under a TLS fixup, so any symbol should be 87 // modified. There should be only one. 88 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 89 cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 90 break; 91 } 92 93 case MCExpr::Unary: 94 fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 95 break; 96 } 97 } 98 99 void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 100 switch (getKind()) { 101 default: 102 return; 103 case VK_CSKY_TLSLE: 104 case VK_CSKY_TLSIE: 105 case VK_CSKY_TLSGD: 106 break; 107 } 108 109 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 110 } 111 112 bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 113 const MCFixup *Fixup) const { 114 if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup)) 115 return false; 116 117 // Some custom fixup types are not valid with symbol difference expressions 118 if (Res.getSymA() && Res.getSymB()) { 119 switch (getKind()) { 120 default: 121 return true; 122 case VK_CSKY_GOT: 123 case VK_CSKY_GOT_IMM18_BY4: 124 case VK_CSKY_GOTPC: 125 case VK_CSKY_GOTOFF: 126 case VK_CSKY_PLT: 127 case VK_CSKY_PLT_IMM18_BY4: 128 case VK_CSKY_TLSIE: 129 case VK_CSKY_TLSLE: 130 case VK_CSKY_TLSGD: 131 case VK_CSKY_TLSLDO: 132 case VK_CSKY_TLSLDM: 133 return false; 134 } 135 } 136 137 return true; 138 } 139