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