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 18using namespace llvm; 19 20#define DEBUG_TYPE "csky-mc-expr" 21 22const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind, 23 MCContext &Ctx) { 24 return new (Ctx) CSKYMCExpr(Kind, Expr); 25} 26 27StringRef 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 61void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 62 Streamer.visitUsedExpr(*getSubExpr()); 63} 64 65void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 66 Expr->print(OS, MAI); 67 OS << getVariantKindName(getKind()); 68} 69 70static 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 99void 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 112bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 113 const MCAsmLayout *Layout, 114 const MCFixup *Fixup) const { 115 if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) 116 return false; 117 118 // Some custom fixup types are not valid with symbol difference expressions 119 if (Res.getSymA() && Res.getSymB()) { 120 switch (getKind()) { 121 default: 122 return true; 123 case VK_CSKY_GOT: 124 case VK_CSKY_GOT_IMM18_BY4: 125 case VK_CSKY_GOTPC: 126 case VK_CSKY_GOTOFF: 127 case VK_CSKY_PLT: 128 case VK_CSKY_PLT_IMM18_BY4: 129 case VK_CSKY_TLSIE: 130 case VK_CSKY_TLSLE: 131 case VK_CSKY_TLSGD: 132 case VK_CSKY_TLSLDO: 133 case VK_CSKY_TLSLDM: 134 return false; 135 } 136 } 137 138 return true; 139} 140