10b57cec5SDimitry Andric //===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the implementation of the assembly expression modifiers 100b57cec5SDimitry Andric // accepted by the Sparc architecture (e.g. "%hi", "%lo", ...). 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "SparcMCExpr.h" 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 160b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 170b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 2081ad6265SDimitry Andric #include "llvm/Support/Casting.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define DEBUG_TYPE "sparcmcexpr" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric const SparcMCExpr* 270b57cec5SDimitry Andric SparcMCExpr::create(VariantKind Kind, const MCExpr *Expr, 280b57cec5SDimitry Andric MCContext &Ctx) { 290b57cec5SDimitry Andric return new (Ctx) SparcMCExpr(Kind, Expr); 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric void SparcMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric bool closeParen = printVariantKind(OS, Kind); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric const MCExpr *Expr = getSubExpr(); 370b57cec5SDimitry Andric Expr->print(OS, MAI); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric if (closeParen) 400b57cec5SDimitry Andric OS << ')'; 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) 440b57cec5SDimitry Andric { 450b57cec5SDimitry Andric switch (Kind) { 46e8d8bef9SDimitry Andric case VK_Sparc_None: return false; 47e8d8bef9SDimitry Andric case VK_Sparc_LO: OS << "%lo("; return true; 48e8d8bef9SDimitry Andric case VK_Sparc_HI: OS << "%hi("; return true; 49e8d8bef9SDimitry Andric case VK_Sparc_H44: OS << "%h44("; return true; 50e8d8bef9SDimitry Andric case VK_Sparc_M44: OS << "%m44("; return true; 51e8d8bef9SDimitry Andric case VK_Sparc_L44: OS << "%l44("; return true; 52e8d8bef9SDimitry Andric case VK_Sparc_HH: OS << "%hh("; return true; 53e8d8bef9SDimitry Andric case VK_Sparc_HM: OS << "%hm("; return true; 54fe6060f1SDimitry Andric case VK_Sparc_LM: OS << "%lm("; return true; 550b57cec5SDimitry Andric // FIXME: use %pc22/%pc10, if system assembler supports them. 56e8d8bef9SDimitry Andric case VK_Sparc_PC22: OS << "%hi("; return true; 57e8d8bef9SDimitry Andric case VK_Sparc_PC10: OS << "%lo("; return true; 580b57cec5SDimitry Andric // FIXME: use %got22/%got10, if system assembler supports them. 59e8d8bef9SDimitry Andric case VK_Sparc_GOT22: OS << "%hi("; return true; 60e8d8bef9SDimitry Andric case VK_Sparc_GOT10: OS << "%lo("; return true; 61e8d8bef9SDimitry Andric case VK_Sparc_GOT13: return false; 62e8d8bef9SDimitry Andric case VK_Sparc_13: return false; 63e8d8bef9SDimitry Andric case VK_Sparc_WDISP30: return false; 64e8d8bef9SDimitry Andric case VK_Sparc_WPLT30: return false; 65e8d8bef9SDimitry Andric case VK_Sparc_R_DISP32: OS << "%r_disp32("; return true; 66e8d8bef9SDimitry Andric case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; return true; 67e8d8bef9SDimitry Andric case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; return true; 68e8d8bef9SDimitry Andric case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; return true; 69e8d8bef9SDimitry Andric case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; return true; 70e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; return true; 71e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; return true; 72e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; return true; 73e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; return true; 74e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; return true; 75e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; return true; 76e8d8bef9SDimitry Andric case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; return true; 77e8d8bef9SDimitry Andric case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; return true; 78e8d8bef9SDimitry Andric case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; return true; 79e8d8bef9SDimitry Andric case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; return true; 80e8d8bef9SDimitry Andric case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; return true; 81e8d8bef9SDimitry Andric case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; return true; 82e8d8bef9SDimitry Andric case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; return true; 83e8d8bef9SDimitry Andric case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; return true; 8481ad6265SDimitry Andric case VK_Sparc_HIX22: OS << "%hix("; return true; 8581ad6265SDimitry Andric case VK_Sparc_LOX10: OS << "%lox("; return true; 8681ad6265SDimitry Andric case VK_Sparc_GOTDATA_HIX22: OS << "%gdop_hix22("; return true; 8781ad6265SDimitry Andric case VK_Sparc_GOTDATA_LOX10: OS << "%gdop_lox10("; return true; 8881ad6265SDimitry Andric case VK_Sparc_GOTDATA_OP: OS << "%gdop("; return true; 890b57cec5SDimitry Andric } 90e8d8bef9SDimitry Andric llvm_unreachable("Unhandled SparcMCExpr::VariantKind"); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) 940b57cec5SDimitry Andric { 950b57cec5SDimitry Andric return StringSwitch<SparcMCExpr::VariantKind>(name) 960b57cec5SDimitry Andric .Case("lo", VK_Sparc_LO) 970b57cec5SDimitry Andric .Case("hi", VK_Sparc_HI) 980b57cec5SDimitry Andric .Case("h44", VK_Sparc_H44) 990b57cec5SDimitry Andric .Case("m44", VK_Sparc_M44) 1000b57cec5SDimitry Andric .Case("l44", VK_Sparc_L44) 1010b57cec5SDimitry Andric .Case("hh", VK_Sparc_HH) 102*0fca6ea1SDimitry Andric .Case("uhi", VK_Sparc_HH) // Nonstandard GNU extension 1030b57cec5SDimitry Andric .Case("hm", VK_Sparc_HM) 104*0fca6ea1SDimitry Andric .Case("ulo", VK_Sparc_HM) // Nonstandard GNU extension 105fe6060f1SDimitry Andric .Case("lm", VK_Sparc_LM) 1060b57cec5SDimitry Andric .Case("pc22", VK_Sparc_PC22) 1070b57cec5SDimitry Andric .Case("pc10", VK_Sparc_PC10) 1080b57cec5SDimitry Andric .Case("got22", VK_Sparc_GOT22) 1090b57cec5SDimitry Andric .Case("got10", VK_Sparc_GOT10) 1100b57cec5SDimitry Andric .Case("got13", VK_Sparc_GOT13) 1110b57cec5SDimitry Andric .Case("r_disp32", VK_Sparc_R_DISP32) 1120b57cec5SDimitry Andric .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) 1130b57cec5SDimitry Andric .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) 1140b57cec5SDimitry Andric .Case("tgd_add", VK_Sparc_TLS_GD_ADD) 1150b57cec5SDimitry Andric .Case("tgd_call", VK_Sparc_TLS_GD_CALL) 1160b57cec5SDimitry Andric .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22) 1170b57cec5SDimitry Andric .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10) 1180b57cec5SDimitry Andric .Case("tldm_add", VK_Sparc_TLS_LDM_ADD) 1190b57cec5SDimitry Andric .Case("tldm_call", VK_Sparc_TLS_LDM_CALL) 1200b57cec5SDimitry Andric .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22) 1210b57cec5SDimitry Andric .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10) 1220b57cec5SDimitry Andric .Case("tldo_add", VK_Sparc_TLS_LDO_ADD) 1230b57cec5SDimitry Andric .Case("tie_hi22", VK_Sparc_TLS_IE_HI22) 1240b57cec5SDimitry Andric .Case("tie_lo10", VK_Sparc_TLS_IE_LO10) 1250b57cec5SDimitry Andric .Case("tie_ld", VK_Sparc_TLS_IE_LD) 1260b57cec5SDimitry Andric .Case("tie_ldx", VK_Sparc_TLS_IE_LDX) 1270b57cec5SDimitry Andric .Case("tie_add", VK_Sparc_TLS_IE_ADD) 1280b57cec5SDimitry Andric .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22) 1290b57cec5SDimitry Andric .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10) 13081ad6265SDimitry Andric .Case("hix", VK_Sparc_HIX22) 13181ad6265SDimitry Andric .Case("lox", VK_Sparc_LOX10) 13281ad6265SDimitry Andric .Case("gdop_hix22", VK_Sparc_GOTDATA_HIX22) 13381ad6265SDimitry Andric .Case("gdop_lox10", VK_Sparc_GOTDATA_LOX10) 13481ad6265SDimitry Andric .Case("gdop", VK_Sparc_GOTDATA_OP) 1350b57cec5SDimitry Andric .Default(VK_Sparc_None); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { 1390b57cec5SDimitry Andric switch (Kind) { 1400b57cec5SDimitry Andric default: llvm_unreachable("Unhandled SparcMCExpr::VariantKind"); 1410b57cec5SDimitry Andric case VK_Sparc_LO: return Sparc::fixup_sparc_lo10; 1420b57cec5SDimitry Andric case VK_Sparc_HI: return Sparc::fixup_sparc_hi22; 1430b57cec5SDimitry Andric case VK_Sparc_H44: return Sparc::fixup_sparc_h44; 1440b57cec5SDimitry Andric case VK_Sparc_M44: return Sparc::fixup_sparc_m44; 1450b57cec5SDimitry Andric case VK_Sparc_L44: return Sparc::fixup_sparc_l44; 1460b57cec5SDimitry Andric case VK_Sparc_HH: return Sparc::fixup_sparc_hh; 1470b57cec5SDimitry Andric case VK_Sparc_HM: return Sparc::fixup_sparc_hm; 148fe6060f1SDimitry Andric case VK_Sparc_LM: return Sparc::fixup_sparc_lm; 1490b57cec5SDimitry Andric case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22; 1500b57cec5SDimitry Andric case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; 1510b57cec5SDimitry Andric case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; 1520b57cec5SDimitry Andric case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; 1530b57cec5SDimitry Andric case VK_Sparc_GOT13: return Sparc::fixup_sparc_got13; 1540b57cec5SDimitry Andric case VK_Sparc_13: return Sparc::fixup_sparc_13; 1550b57cec5SDimitry Andric case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30; 156e8d8bef9SDimitry Andric case VK_Sparc_WDISP30: return Sparc::fixup_sparc_call30; 1570b57cec5SDimitry Andric case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22; 1580b57cec5SDimitry Andric case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10; 1590b57cec5SDimitry Andric case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add; 1600b57cec5SDimitry Andric case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call; 1610b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22; 1620b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10; 1630b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add; 1640b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call; 1650b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22; 1660b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10; 1670b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add; 1680b57cec5SDimitry Andric case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22; 1690b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10; 1700b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld; 1710b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx; 1720b57cec5SDimitry Andric case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add; 1730b57cec5SDimitry Andric case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22; 1740b57cec5SDimitry Andric case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10; 17581ad6265SDimitry Andric case VK_Sparc_HIX22: return Sparc::fixup_sparc_hix22; 17681ad6265SDimitry Andric case VK_Sparc_LOX10: return Sparc::fixup_sparc_lox10; 17781ad6265SDimitry Andric case VK_Sparc_GOTDATA_HIX22: return Sparc::fixup_sparc_gotdata_hix22; 17881ad6265SDimitry Andric case VK_Sparc_GOTDATA_LOX10: return Sparc::fixup_sparc_gotdata_lox10; 17981ad6265SDimitry Andric case VK_Sparc_GOTDATA_OP: return Sparc::fixup_sparc_gotdata_op; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183*0fca6ea1SDimitry Andric bool SparcMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 184*0fca6ea1SDimitry Andric const MCAssembler *Asm, 1850b57cec5SDimitry Andric const MCFixup *Fixup) const { 186*0fca6ea1SDimitry Andric return getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { 1900b57cec5SDimitry Andric switch (Expr->getKind()) { 1910b57cec5SDimitry Andric case MCExpr::Target: 1920b57cec5SDimitry Andric llvm_unreachable("Can't handle nested target expr!"); 1930b57cec5SDimitry Andric break; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric case MCExpr::Constant: 1960b57cec5SDimitry Andric break; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric case MCExpr::Binary: { 1990b57cec5SDimitry Andric const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); 2000b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); 2010b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); 2020b57cec5SDimitry Andric break; 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric case MCExpr::SymbolRef: { 2060b57cec5SDimitry Andric const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); 2070b57cec5SDimitry Andric cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); 2080b57cec5SDimitry Andric break; 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric case MCExpr::Unary: 2120b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); 2130b57cec5SDimitry Andric break; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { 2190b57cec5SDimitry Andric switch(getKind()) { 2200b57cec5SDimitry Andric default: return; 2210b57cec5SDimitry Andric case VK_Sparc_TLS_GD_CALL: 2220b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_CALL: { 2230b57cec5SDimitry Andric // The corresponding relocations reference __tls_get_addr, as they call it, 2240b57cec5SDimitry Andric // but this is only implicit; we must explicitly add it to our symbol table 2250b57cec5SDimitry Andric // to bind it for these uses. 2260b57cec5SDimitry Andric MCSymbol *Symbol = Asm.getContext().getOrCreateSymbol("__tls_get_addr"); 2270b57cec5SDimitry Andric Asm.registerSymbol(*Symbol); 2280b57cec5SDimitry Andric auto ELFSymbol = cast<MCSymbolELF>(Symbol); 229e8d8bef9SDimitry Andric if (!ELFSymbol->isBindingSet()) 2300b57cec5SDimitry Andric ELFSymbol->setBinding(ELF::STB_GLOBAL); 231bdd1243dSDimitry Andric [[fallthrough]]; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric case VK_Sparc_TLS_GD_HI22: 2340b57cec5SDimitry Andric case VK_Sparc_TLS_GD_LO10: 2350b57cec5SDimitry Andric case VK_Sparc_TLS_GD_ADD: 2360b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_HI22: 2370b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_LO10: 2380b57cec5SDimitry Andric case VK_Sparc_TLS_LDM_ADD: 2390b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_HIX22: 2400b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_LOX10: 2410b57cec5SDimitry Andric case VK_Sparc_TLS_LDO_ADD: 2420b57cec5SDimitry Andric case VK_Sparc_TLS_IE_HI22: 2430b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LO10: 2440b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LD: 2450b57cec5SDimitry Andric case VK_Sparc_TLS_IE_LDX: 2460b57cec5SDimitry Andric case VK_Sparc_TLS_IE_ADD: 2470b57cec5SDimitry Andric case VK_Sparc_TLS_LE_HIX22: 2480b57cec5SDimitry Andric case VK_Sparc_TLS_LE_LOX10: break; 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric void SparcMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 2540b57cec5SDimitry Andric Streamer.visitUsedExpr(*getSubExpr()); 2550b57cec5SDimitry Andric } 256