1*5ffd83dbSDimitry Andric //===-- VEMCExpr.cpp - VE specific MC expression classes ------------------===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric // 9*5ffd83dbSDimitry Andric // This file contains the implementation of the assembly expression modifiers 10*5ffd83dbSDimitry Andric // accepted by the VE architecture (e.g. "%hi", "%lo", ...). 11*5ffd83dbSDimitry Andric // 12*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 13*5ffd83dbSDimitry Andric 14*5ffd83dbSDimitry Andric #include "VEMCExpr.h" 15*5ffd83dbSDimitry Andric #include "llvm/MC/MCAssembler.h" 16*5ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 17*5ffd83dbSDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 18*5ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolELF.h" 19*5ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 20*5ffd83dbSDimitry Andric 21*5ffd83dbSDimitry Andric using namespace llvm; 22*5ffd83dbSDimitry Andric 23*5ffd83dbSDimitry Andric #define DEBUG_TYPE "vemcexpr" 24*5ffd83dbSDimitry Andric 25*5ffd83dbSDimitry Andric const VEMCExpr *VEMCExpr::create(VariantKind Kind, const MCExpr *Expr, 26*5ffd83dbSDimitry Andric MCContext &Ctx) { 27*5ffd83dbSDimitry Andric return new (Ctx) VEMCExpr(Kind, Expr); 28*5ffd83dbSDimitry Andric } 29*5ffd83dbSDimitry Andric 30*5ffd83dbSDimitry Andric void VEMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 31*5ffd83dbSDimitry Andric 32*5ffd83dbSDimitry Andric bool closeParen = printVariantKind(OS, Kind); 33*5ffd83dbSDimitry Andric 34*5ffd83dbSDimitry Andric const MCExpr *Expr = getSubExpr(); 35*5ffd83dbSDimitry Andric Expr->print(OS, MAI); 36*5ffd83dbSDimitry Andric 37*5ffd83dbSDimitry Andric if (closeParen) 38*5ffd83dbSDimitry Andric OS << ')'; 39*5ffd83dbSDimitry Andric printVariantKindSuffix(OS, Kind); 40*5ffd83dbSDimitry Andric } 41*5ffd83dbSDimitry Andric 42*5ffd83dbSDimitry Andric bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) { 43*5ffd83dbSDimitry Andric switch (Kind) { 44*5ffd83dbSDimitry Andric case VK_VE_None: 45*5ffd83dbSDimitry Andric case VK_VE_REFLONG: 46*5ffd83dbSDimitry Andric return false; 47*5ffd83dbSDimitry Andric 48*5ffd83dbSDimitry Andric case VK_VE_HI32: 49*5ffd83dbSDimitry Andric case VK_VE_LO32: 50*5ffd83dbSDimitry Andric case VK_VE_PC_HI32: 51*5ffd83dbSDimitry Andric case VK_VE_PC_LO32: 52*5ffd83dbSDimitry Andric case VK_VE_GOT_HI32: 53*5ffd83dbSDimitry Andric case VK_VE_GOT_LO32: 54*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: 55*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: 56*5ffd83dbSDimitry Andric case VK_VE_PLT_HI32: 57*5ffd83dbSDimitry Andric case VK_VE_PLT_LO32: 58*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: 59*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: 60*5ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: 61*5ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: 62*5ffd83dbSDimitry Andric // Use suffix for these variant kinds 63*5ffd83dbSDimitry Andric return false; 64*5ffd83dbSDimitry Andric } 65*5ffd83dbSDimitry Andric return true; 66*5ffd83dbSDimitry Andric } 67*5ffd83dbSDimitry Andric 68*5ffd83dbSDimitry Andric void VEMCExpr::printVariantKindSuffix(raw_ostream &OS, VariantKind Kind) { 69*5ffd83dbSDimitry Andric switch (Kind) { 70*5ffd83dbSDimitry Andric case VK_VE_None: 71*5ffd83dbSDimitry Andric case VK_VE_REFLONG: 72*5ffd83dbSDimitry Andric break; 73*5ffd83dbSDimitry Andric case VK_VE_HI32: 74*5ffd83dbSDimitry Andric OS << "@hi"; 75*5ffd83dbSDimitry Andric break; 76*5ffd83dbSDimitry Andric case VK_VE_LO32: 77*5ffd83dbSDimitry Andric OS << "@lo"; 78*5ffd83dbSDimitry Andric break; 79*5ffd83dbSDimitry Andric case VK_VE_PC_HI32: 80*5ffd83dbSDimitry Andric OS << "@pc_hi"; 81*5ffd83dbSDimitry Andric break; 82*5ffd83dbSDimitry Andric case VK_VE_PC_LO32: 83*5ffd83dbSDimitry Andric OS << "@pc_lo"; 84*5ffd83dbSDimitry Andric break; 85*5ffd83dbSDimitry Andric case VK_VE_GOT_HI32: 86*5ffd83dbSDimitry Andric OS << "@got_hi"; 87*5ffd83dbSDimitry Andric break; 88*5ffd83dbSDimitry Andric case VK_VE_GOT_LO32: 89*5ffd83dbSDimitry Andric OS << "@got_lo"; 90*5ffd83dbSDimitry Andric break; 91*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: 92*5ffd83dbSDimitry Andric OS << "@gotoff_hi"; 93*5ffd83dbSDimitry Andric break; 94*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: 95*5ffd83dbSDimitry Andric OS << "@gotoff_lo"; 96*5ffd83dbSDimitry Andric break; 97*5ffd83dbSDimitry Andric case VK_VE_PLT_HI32: 98*5ffd83dbSDimitry Andric OS << "@plt_hi"; 99*5ffd83dbSDimitry Andric break; 100*5ffd83dbSDimitry Andric case VK_VE_PLT_LO32: 101*5ffd83dbSDimitry Andric OS << "@plt_lo"; 102*5ffd83dbSDimitry Andric break; 103*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: 104*5ffd83dbSDimitry Andric OS << "@tls_gd_hi"; 105*5ffd83dbSDimitry Andric break; 106*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: 107*5ffd83dbSDimitry Andric OS << "@tls_gd_lo"; 108*5ffd83dbSDimitry Andric break; 109*5ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: 110*5ffd83dbSDimitry Andric OS << "@tpoff_hi"; 111*5ffd83dbSDimitry Andric break; 112*5ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: 113*5ffd83dbSDimitry Andric OS << "@tpoff_lo"; 114*5ffd83dbSDimitry Andric break; 115*5ffd83dbSDimitry Andric } 116*5ffd83dbSDimitry Andric } 117*5ffd83dbSDimitry Andric 118*5ffd83dbSDimitry Andric VEMCExpr::VariantKind VEMCExpr::parseVariantKind(StringRef name) { 119*5ffd83dbSDimitry Andric return StringSwitch<VEMCExpr::VariantKind>(name) 120*5ffd83dbSDimitry Andric .Case("hi", VK_VE_HI32) 121*5ffd83dbSDimitry Andric .Case("lo", VK_VE_LO32) 122*5ffd83dbSDimitry Andric .Case("pc_hi", VK_VE_PC_HI32) 123*5ffd83dbSDimitry Andric .Case("pc_lo", VK_VE_PC_LO32) 124*5ffd83dbSDimitry Andric .Case("got_hi", VK_VE_GOT_HI32) 125*5ffd83dbSDimitry Andric .Case("got_lo", VK_VE_GOT_LO32) 126*5ffd83dbSDimitry Andric .Case("gotoff_hi", VK_VE_GOTOFF_HI32) 127*5ffd83dbSDimitry Andric .Case("gotoff_lo", VK_VE_GOTOFF_LO32) 128*5ffd83dbSDimitry Andric .Case("plt_hi", VK_VE_PLT_HI32) 129*5ffd83dbSDimitry Andric .Case("plt_lo", VK_VE_PLT_LO32) 130*5ffd83dbSDimitry Andric .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) 131*5ffd83dbSDimitry Andric .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) 132*5ffd83dbSDimitry Andric .Case("tpoff_hi", VK_VE_TPOFF_HI32) 133*5ffd83dbSDimitry Andric .Case("tpoff_lo", VK_VE_TPOFF_LO32) 134*5ffd83dbSDimitry Andric .Default(VK_VE_None); 135*5ffd83dbSDimitry Andric } 136*5ffd83dbSDimitry Andric 137*5ffd83dbSDimitry Andric VE::Fixups VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind) { 138*5ffd83dbSDimitry Andric switch (Kind) { 139*5ffd83dbSDimitry Andric default: 140*5ffd83dbSDimitry Andric llvm_unreachable("Unhandled VEMCExpr::VariantKind"); 141*5ffd83dbSDimitry Andric case VK_VE_REFLONG: 142*5ffd83dbSDimitry Andric return VE::fixup_ve_reflong; 143*5ffd83dbSDimitry Andric case VK_VE_HI32: 144*5ffd83dbSDimitry Andric return VE::fixup_ve_hi32; 145*5ffd83dbSDimitry Andric case VK_VE_LO32: 146*5ffd83dbSDimitry Andric return VE::fixup_ve_lo32; 147*5ffd83dbSDimitry Andric case VK_VE_PC_HI32: 148*5ffd83dbSDimitry Andric return VE::fixup_ve_pc_hi32; 149*5ffd83dbSDimitry Andric case VK_VE_PC_LO32: 150*5ffd83dbSDimitry Andric return VE::fixup_ve_pc_lo32; 151*5ffd83dbSDimitry Andric case VK_VE_GOT_HI32: 152*5ffd83dbSDimitry Andric return VE::fixup_ve_got_hi32; 153*5ffd83dbSDimitry Andric case VK_VE_GOT_LO32: 154*5ffd83dbSDimitry Andric return VE::fixup_ve_got_lo32; 155*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_HI32: 156*5ffd83dbSDimitry Andric return VE::fixup_ve_gotoff_hi32; 157*5ffd83dbSDimitry Andric case VK_VE_GOTOFF_LO32: 158*5ffd83dbSDimitry Andric return VE::fixup_ve_gotoff_lo32; 159*5ffd83dbSDimitry Andric case VK_VE_PLT_HI32: 160*5ffd83dbSDimitry Andric return VE::fixup_ve_plt_hi32; 161*5ffd83dbSDimitry Andric case VK_VE_PLT_LO32: 162*5ffd83dbSDimitry Andric return VE::fixup_ve_plt_lo32; 163*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: 164*5ffd83dbSDimitry Andric return VE::fixup_ve_tls_gd_hi32; 165*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: 166*5ffd83dbSDimitry Andric return VE::fixup_ve_tls_gd_lo32; 167*5ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: 168*5ffd83dbSDimitry Andric return VE::fixup_ve_tpoff_hi32; 169*5ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: 170*5ffd83dbSDimitry Andric return VE::fixup_ve_tpoff_lo32; 171*5ffd83dbSDimitry Andric } 172*5ffd83dbSDimitry Andric } 173*5ffd83dbSDimitry Andric 174*5ffd83dbSDimitry Andric bool VEMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 175*5ffd83dbSDimitry Andric const MCAsmLayout *Layout, 176*5ffd83dbSDimitry Andric const MCFixup *Fixup) const { 177*5ffd83dbSDimitry Andric return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); 178*5ffd83dbSDimitry Andric } 179*5ffd83dbSDimitry Andric 180*5ffd83dbSDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 181*5ffd83dbSDimitry Andric switch (Expr->getKind()) { 182*5ffd83dbSDimitry Andric case MCExpr::Target: 183*5ffd83dbSDimitry Andric llvm_unreachable("Can't handle nested target expr!"); 184*5ffd83dbSDimitry Andric break; 185*5ffd83dbSDimitry Andric 186*5ffd83dbSDimitry Andric case MCExpr::Constant: 187*5ffd83dbSDimitry Andric break; 188*5ffd83dbSDimitry Andric 189*5ffd83dbSDimitry Andric case MCExpr::Binary: { 190*5ffd83dbSDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 191*5ffd83dbSDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 192*5ffd83dbSDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 193*5ffd83dbSDimitry Andric break; 194*5ffd83dbSDimitry Andric } 195*5ffd83dbSDimitry Andric 196*5ffd83dbSDimitry Andric case MCExpr::SymbolRef: { 197*5ffd83dbSDimitry Andric // We're known to be under a TLS fixup, so any symbol should be 198*5ffd83dbSDimitry Andric // modified. There should be only one. 199*5ffd83dbSDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 200*5ffd83dbSDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 201*5ffd83dbSDimitry Andric break; 202*5ffd83dbSDimitry Andric } 203*5ffd83dbSDimitry Andric 204*5ffd83dbSDimitry Andric case MCExpr::Unary: 205*5ffd83dbSDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 206*5ffd83dbSDimitry Andric break; 207*5ffd83dbSDimitry Andric } 208*5ffd83dbSDimitry Andric } 209*5ffd83dbSDimitry Andric 210*5ffd83dbSDimitry Andric void VEMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 211*5ffd83dbSDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 212*5ffd83dbSDimitry Andric } 213*5ffd83dbSDimitry Andric 214*5ffd83dbSDimitry Andric void VEMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 215*5ffd83dbSDimitry Andric switch (getKind()) { 216*5ffd83dbSDimitry Andric default: 217*5ffd83dbSDimitry Andric return; 218*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_HI32: 219*5ffd83dbSDimitry Andric case VK_VE_TLS_GD_LO32: 220*5ffd83dbSDimitry Andric case VK_VE_TPOFF_HI32: 221*5ffd83dbSDimitry Andric case VK_VE_TPOFF_LO32: 222*5ffd83dbSDimitry Andric break; 223*5ffd83dbSDimitry Andric } 224*5ffd83dbSDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 225*5ffd83dbSDimitry Andric } 226