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_ADDR: 30 return ""; 31 case VK_CSKY_PCREL: 32 return ""; 33 case VK_CSKY_GOT: 34 return "@GOT"; 35 case VK_CSKY_GOTPC: 36 return "@GOTPC"; 37 case VK_CSKY_GOTOFF: 38 return "@GOTOFF"; 39 case VK_CSKY_PLT: 40 return "@PLT"; 41 case VK_CSKY_TPOFF: 42 return "@TPOFF"; 43 case VK_CSKY_TLSGD: 44 return "@TLSGD"; 45 } 46 } 47 48 void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 49 Streamer.visitUsedExpr(*getSubExpr()); 50 } 51 52 void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 53 Expr->print(OS, MAI); 54 OS << getVariantKindName(getKind()); 55 } 56 57 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 58 switch (Expr->getKind()) { 59 case MCExpr::Target: 60 llvm_unreachable("Can't handle nested target expression"); 61 break; 62 case MCExpr::Constant: 63 break; 64 65 case MCExpr::Binary: { 66 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 67 fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 68 fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 69 break; 70 } 71 72 case MCExpr::SymbolRef: { 73 // We're known to be under a TLS fixup, so any symbol should be 74 // modified. There should be only one. 75 const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 76 cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 77 break; 78 } 79 80 case MCExpr::Unary: 81 fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 82 break; 83 } 84 } 85 86 void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 87 switch (getKind()) { 88 default: 89 return; 90 case VK_CSKY_TPOFF: 91 case VK_CSKY_TLSGD: 92 break; 93 } 94 95 fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 96 } 97 98 bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 99 const MCAsmLayout *Layout, 100 const MCFixup *Fixup) const { 101 if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) 102 return false; 103 104 // Some custom fixup types are not valid with symbol difference expressions 105 if (Res.getSymA() && Res.getSymB()) { 106 switch (getKind()) { 107 default: 108 return true; 109 110 case VK_CSKY_ADDR: 111 case VK_CSKY_PCREL: 112 case VK_CSKY_GOT: 113 case VK_CSKY_GOTPC: 114 case VK_CSKY_GOTOFF: 115 case VK_CSKY_TPOFF: 116 case VK_CSKY_TLSGD: 117 return false; 118 } 119 } 120 121 return true; 122 }