1fe6060f1SDimitry Andric //===-- CSKYMCExpr.cpp - CSKY specific MC expression classes -*- C++ -*----===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric 9fe6060f1SDimitry Andric #include "CSKYMCExpr.h" 10fe6060f1SDimitry Andric #include "CSKYFixupKinds.h" 1181ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 12fe6060f1SDimitry Andric #include "llvm/MC/MCAssembler.h" 13fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h" 14fe6060f1SDimitry Andric #include "llvm/MC/MCStreamer.h" 15fe6060f1SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 1681ad6265SDimitry Andric #include "llvm/Support/Casting.h" 17fe6060f1SDimitry Andric 18fe6060f1SDimitry Andric using namespace llvm; 19fe6060f1SDimitry Andric 20fe6060f1SDimitry Andric #define DEBUG_TYPE "csky-mc-expr" 21fe6060f1SDimitry Andric 22fe6060f1SDimitry Andric const CSKYMCExpr *CSKYMCExpr::create(const MCExpr *Expr, VariantKind Kind, 23fe6060f1SDimitry Andric MCContext &Ctx) { 24fe6060f1SDimitry Andric return new (Ctx) CSKYMCExpr(Kind, Expr); 25fe6060f1SDimitry Andric } 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric StringRef CSKYMCExpr::getVariantKindName(VariantKind Kind) { 28fe6060f1SDimitry Andric switch (Kind) { 29fe6060f1SDimitry Andric default: 30fe6060f1SDimitry Andric llvm_unreachable("Invalid ELF symbol kind"); 31349cc55cSDimitry Andric case VK_CSKY_None: 32fe6060f1SDimitry Andric case VK_CSKY_ADDR: 33fe6060f1SDimitry Andric return ""; 34349cc55cSDimitry Andric case VK_CSKY_ADDR_HI16: 35349cc55cSDimitry Andric return "@HI16"; 36349cc55cSDimitry Andric case VK_CSKY_ADDR_LO16: 37349cc55cSDimitry Andric return "@LO16"; 38349cc55cSDimitry Andric case VK_CSKY_GOT_IMM18_BY4: 39fe6060f1SDimitry Andric case VK_CSKY_GOT: 40fe6060f1SDimitry Andric return "@GOT"; 41fe6060f1SDimitry Andric case VK_CSKY_GOTPC: 42fe6060f1SDimitry Andric return "@GOTPC"; 43fe6060f1SDimitry Andric case VK_CSKY_GOTOFF: 44fe6060f1SDimitry Andric return "@GOTOFF"; 45349cc55cSDimitry Andric case VK_CSKY_PLT_IMM18_BY4: 46fe6060f1SDimitry Andric case VK_CSKY_PLT: 47fe6060f1SDimitry Andric return "@PLT"; 48349cc55cSDimitry Andric case VK_CSKY_TLSLE: 49fe6060f1SDimitry Andric return "@TPOFF"; 50349cc55cSDimitry Andric case VK_CSKY_TLSIE: 51349cc55cSDimitry Andric return "@GOTTPOFF"; 52fe6060f1SDimitry Andric case VK_CSKY_TLSGD: 53349cc55cSDimitry Andric return "@TLSGD32"; 54349cc55cSDimitry Andric case VK_CSKY_TLSLDO: 55349cc55cSDimitry Andric return "@TLSLDO32"; 56349cc55cSDimitry Andric case VK_CSKY_TLSLDM: 57349cc55cSDimitry Andric return "@TLSLDM32"; 58fe6060f1SDimitry Andric } 59fe6060f1SDimitry Andric } 60fe6060f1SDimitry Andric 61fe6060f1SDimitry Andric void CSKYMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 62fe6060f1SDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 63fe6060f1SDimitry Andric } 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric void CSKYMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 66fe6060f1SDimitry Andric Expr->print(OS, MAI); 67fe6060f1SDimitry Andric OS << getVariantKindName(getKind()); 68fe6060f1SDimitry Andric } 69fe6060f1SDimitry Andric 70fe6060f1SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 71fe6060f1SDimitry Andric switch (Expr->getKind()) { 72fe6060f1SDimitry Andric case MCExpr::Target: 73fe6060f1SDimitry Andric llvm_unreachable("Can't handle nested target expression"); 74fe6060f1SDimitry Andric break; 75fe6060f1SDimitry Andric case MCExpr::Constant: 76fe6060f1SDimitry Andric break; 77fe6060f1SDimitry Andric 78fe6060f1SDimitry Andric case MCExpr::Binary: { 79fe6060f1SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 80fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 81fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 82fe6060f1SDimitry Andric break; 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric 85fe6060f1SDimitry Andric case MCExpr::SymbolRef: { 86fe6060f1SDimitry Andric // We're known to be under a TLS fixup, so any symbol should be 87fe6060f1SDimitry Andric // modified. There should be only one. 88fe6060f1SDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 89fe6060f1SDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 90fe6060f1SDimitry Andric break; 91fe6060f1SDimitry Andric } 92fe6060f1SDimitry Andric 93fe6060f1SDimitry Andric case MCExpr::Unary: 94fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 95fe6060f1SDimitry Andric break; 96fe6060f1SDimitry Andric } 97fe6060f1SDimitry Andric } 98fe6060f1SDimitry Andric 99fe6060f1SDimitry Andric void CSKYMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 100fe6060f1SDimitry Andric switch (getKind()) { 101fe6060f1SDimitry Andric default: 102fe6060f1SDimitry Andric return; 103349cc55cSDimitry Andric case VK_CSKY_TLSLE: 104349cc55cSDimitry Andric case VK_CSKY_TLSIE: 105fe6060f1SDimitry Andric case VK_CSKY_TLSGD: 106fe6060f1SDimitry Andric break; 107fe6060f1SDimitry Andric } 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric 112*0fca6ea1SDimitry Andric bool CSKYMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 113fe6060f1SDimitry Andric const MCFixup *Fixup) const { 114*0fca6ea1SDimitry Andric if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup)) 115fe6060f1SDimitry Andric return false; 116fe6060f1SDimitry Andric 117fe6060f1SDimitry Andric // Some custom fixup types are not valid with symbol difference expressions 118fe6060f1SDimitry Andric if (Res.getSymA() && Res.getSymB()) { 119fe6060f1SDimitry Andric switch (getKind()) { 120fe6060f1SDimitry Andric default: 121fe6060f1SDimitry Andric return true; 122fe6060f1SDimitry Andric case VK_CSKY_GOT: 123349cc55cSDimitry Andric case VK_CSKY_GOT_IMM18_BY4: 124fe6060f1SDimitry Andric case VK_CSKY_GOTPC: 125fe6060f1SDimitry Andric case VK_CSKY_GOTOFF: 126349cc55cSDimitry Andric case VK_CSKY_PLT: 127349cc55cSDimitry Andric case VK_CSKY_PLT_IMM18_BY4: 128349cc55cSDimitry Andric case VK_CSKY_TLSIE: 129349cc55cSDimitry Andric case VK_CSKY_TLSLE: 130fe6060f1SDimitry Andric case VK_CSKY_TLSGD: 131349cc55cSDimitry Andric case VK_CSKY_TLSLDO: 132349cc55cSDimitry Andric case VK_CSKY_TLSLDM: 133fe6060f1SDimitry Andric return false; 134fe6060f1SDimitry Andric } 135fe6060f1SDimitry Andric } 136fe6060f1SDimitry Andric 137fe6060f1SDimitry Andric return true; 138fe6060f1SDimitry Andric } 139