xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/MCTargetDesc/VEMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- VEMCExpr.cpp - VE specific MC expression classes ------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric //
95ffd83dbSDimitry Andric // This file contains the implementation of the assembly expression modifiers
105ffd83dbSDimitry Andric // accepted by the VE architecture (e.g. "%hi", "%lo", ...).
115ffd83dbSDimitry Andric //
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "VEMCExpr.h"
150eae32dcSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
165ffd83dbSDimitry Andric #include "llvm/MC/MCAssembler.h"
175ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
185ffd83dbSDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
195ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolELF.h"
200eae32dcSDimitry Andric #include "llvm/MC/MCValue.h"
2181ad6265SDimitry Andric #include "llvm/Support/Casting.h"
225ffd83dbSDimitry Andric 
235ffd83dbSDimitry Andric using namespace llvm;
245ffd83dbSDimitry Andric 
255ffd83dbSDimitry Andric #define DEBUG_TYPE "vemcexpr"
265ffd83dbSDimitry Andric 
create(VariantKind Kind,const MCExpr * Expr,MCContext & Ctx)275ffd83dbSDimitry Andric const VEMCExpr *VEMCExpr::create(VariantKind Kind, const MCExpr *Expr,
285ffd83dbSDimitry Andric                                  MCContext &Ctx) {
295ffd83dbSDimitry Andric   return new (Ctx) VEMCExpr(Kind, Expr);
305ffd83dbSDimitry Andric }
315ffd83dbSDimitry Andric 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const325ffd83dbSDimitry Andric void VEMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
335ffd83dbSDimitry Andric 
345ffd83dbSDimitry Andric   bool closeParen = printVariantKind(OS, Kind);
355ffd83dbSDimitry Andric 
365ffd83dbSDimitry Andric   const MCExpr *Expr = getSubExpr();
375ffd83dbSDimitry Andric   Expr->print(OS, MAI);
385ffd83dbSDimitry Andric 
395ffd83dbSDimitry Andric   if (closeParen)
405ffd83dbSDimitry Andric     OS << ')';
415ffd83dbSDimitry Andric   printVariantKindSuffix(OS, Kind);
425ffd83dbSDimitry Andric }
435ffd83dbSDimitry Andric 
printVariantKind(raw_ostream & OS,VariantKind Kind)445ffd83dbSDimitry Andric bool VEMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) {
455ffd83dbSDimitry Andric   switch (Kind) {
465ffd83dbSDimitry Andric   case VK_VE_None:
475ffd83dbSDimitry Andric   case VK_VE_REFLONG:
485ffd83dbSDimitry Andric     return false;
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric   case VK_VE_HI32:
515ffd83dbSDimitry Andric   case VK_VE_LO32:
525ffd83dbSDimitry Andric   case VK_VE_PC_HI32:
535ffd83dbSDimitry Andric   case VK_VE_PC_LO32:
545ffd83dbSDimitry Andric   case VK_VE_GOT_HI32:
555ffd83dbSDimitry Andric   case VK_VE_GOT_LO32:
565ffd83dbSDimitry Andric   case VK_VE_GOTOFF_HI32:
575ffd83dbSDimitry Andric   case VK_VE_GOTOFF_LO32:
585ffd83dbSDimitry Andric   case VK_VE_PLT_HI32:
595ffd83dbSDimitry Andric   case VK_VE_PLT_LO32:
605ffd83dbSDimitry Andric   case VK_VE_TLS_GD_HI32:
615ffd83dbSDimitry Andric   case VK_VE_TLS_GD_LO32:
625ffd83dbSDimitry Andric   case VK_VE_TPOFF_HI32:
635ffd83dbSDimitry Andric   case VK_VE_TPOFF_LO32:
645ffd83dbSDimitry Andric     // Use suffix for these variant kinds
655ffd83dbSDimitry Andric     return false;
665ffd83dbSDimitry Andric   }
675ffd83dbSDimitry Andric   return true;
685ffd83dbSDimitry Andric }
695ffd83dbSDimitry Andric 
printVariantKindSuffix(raw_ostream & OS,VariantKind Kind)705ffd83dbSDimitry Andric void VEMCExpr::printVariantKindSuffix(raw_ostream &OS, VariantKind Kind) {
715ffd83dbSDimitry Andric   switch (Kind) {
725ffd83dbSDimitry Andric   case VK_VE_None:
735ffd83dbSDimitry Andric   case VK_VE_REFLONG:
745ffd83dbSDimitry Andric     break;
755ffd83dbSDimitry Andric   case VK_VE_HI32:
765ffd83dbSDimitry Andric     OS << "@hi";
775ffd83dbSDimitry Andric     break;
785ffd83dbSDimitry Andric   case VK_VE_LO32:
795ffd83dbSDimitry Andric     OS << "@lo";
805ffd83dbSDimitry Andric     break;
815ffd83dbSDimitry Andric   case VK_VE_PC_HI32:
825ffd83dbSDimitry Andric     OS << "@pc_hi";
835ffd83dbSDimitry Andric     break;
845ffd83dbSDimitry Andric   case VK_VE_PC_LO32:
855ffd83dbSDimitry Andric     OS << "@pc_lo";
865ffd83dbSDimitry Andric     break;
875ffd83dbSDimitry Andric   case VK_VE_GOT_HI32:
885ffd83dbSDimitry Andric     OS << "@got_hi";
895ffd83dbSDimitry Andric     break;
905ffd83dbSDimitry Andric   case VK_VE_GOT_LO32:
915ffd83dbSDimitry Andric     OS << "@got_lo";
925ffd83dbSDimitry Andric     break;
935ffd83dbSDimitry Andric   case VK_VE_GOTOFF_HI32:
945ffd83dbSDimitry Andric     OS << "@gotoff_hi";
955ffd83dbSDimitry Andric     break;
965ffd83dbSDimitry Andric   case VK_VE_GOTOFF_LO32:
975ffd83dbSDimitry Andric     OS << "@gotoff_lo";
985ffd83dbSDimitry Andric     break;
995ffd83dbSDimitry Andric   case VK_VE_PLT_HI32:
1005ffd83dbSDimitry Andric     OS << "@plt_hi";
1015ffd83dbSDimitry Andric     break;
1025ffd83dbSDimitry Andric   case VK_VE_PLT_LO32:
1035ffd83dbSDimitry Andric     OS << "@plt_lo";
1045ffd83dbSDimitry Andric     break;
1055ffd83dbSDimitry Andric   case VK_VE_TLS_GD_HI32:
1065ffd83dbSDimitry Andric     OS << "@tls_gd_hi";
1075ffd83dbSDimitry Andric     break;
1085ffd83dbSDimitry Andric   case VK_VE_TLS_GD_LO32:
1095ffd83dbSDimitry Andric     OS << "@tls_gd_lo";
1105ffd83dbSDimitry Andric     break;
1115ffd83dbSDimitry Andric   case VK_VE_TPOFF_HI32:
1125ffd83dbSDimitry Andric     OS << "@tpoff_hi";
1135ffd83dbSDimitry Andric     break;
1145ffd83dbSDimitry Andric   case VK_VE_TPOFF_LO32:
1155ffd83dbSDimitry Andric     OS << "@tpoff_lo";
1165ffd83dbSDimitry Andric     break;
1175ffd83dbSDimitry Andric   }
1185ffd83dbSDimitry Andric }
1195ffd83dbSDimitry Andric 
parseVariantKind(StringRef name)1205ffd83dbSDimitry Andric VEMCExpr::VariantKind VEMCExpr::parseVariantKind(StringRef name) {
1215ffd83dbSDimitry Andric   return StringSwitch<VEMCExpr::VariantKind>(name)
1225ffd83dbSDimitry Andric       .Case("hi", VK_VE_HI32)
1235ffd83dbSDimitry Andric       .Case("lo", VK_VE_LO32)
1245ffd83dbSDimitry Andric       .Case("pc_hi", VK_VE_PC_HI32)
1255ffd83dbSDimitry Andric       .Case("pc_lo", VK_VE_PC_LO32)
1265ffd83dbSDimitry Andric       .Case("got_hi", VK_VE_GOT_HI32)
1275ffd83dbSDimitry Andric       .Case("got_lo", VK_VE_GOT_LO32)
1285ffd83dbSDimitry Andric       .Case("gotoff_hi", VK_VE_GOTOFF_HI32)
1295ffd83dbSDimitry Andric       .Case("gotoff_lo", VK_VE_GOTOFF_LO32)
1305ffd83dbSDimitry Andric       .Case("plt_hi", VK_VE_PLT_HI32)
1315ffd83dbSDimitry Andric       .Case("plt_lo", VK_VE_PLT_LO32)
1325ffd83dbSDimitry Andric       .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
1335ffd83dbSDimitry Andric       .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
1345ffd83dbSDimitry Andric       .Case("tpoff_hi", VK_VE_TPOFF_HI32)
1355ffd83dbSDimitry Andric       .Case("tpoff_lo", VK_VE_TPOFF_LO32)
1365ffd83dbSDimitry Andric       .Default(VK_VE_None);
1375ffd83dbSDimitry Andric }
1385ffd83dbSDimitry Andric 
getFixupKind(VEMCExpr::VariantKind Kind)1395ffd83dbSDimitry Andric VE::Fixups VEMCExpr::getFixupKind(VEMCExpr::VariantKind Kind) {
1405ffd83dbSDimitry Andric   switch (Kind) {
1415ffd83dbSDimitry Andric   default:
1425ffd83dbSDimitry Andric     llvm_unreachable("Unhandled VEMCExpr::VariantKind");
1435ffd83dbSDimitry Andric   case VK_VE_REFLONG:
1445ffd83dbSDimitry Andric     return VE::fixup_ve_reflong;
1455ffd83dbSDimitry Andric   case VK_VE_HI32:
1465ffd83dbSDimitry Andric     return VE::fixup_ve_hi32;
1475ffd83dbSDimitry Andric   case VK_VE_LO32:
1485ffd83dbSDimitry Andric     return VE::fixup_ve_lo32;
1495ffd83dbSDimitry Andric   case VK_VE_PC_HI32:
1505ffd83dbSDimitry Andric     return VE::fixup_ve_pc_hi32;
1515ffd83dbSDimitry Andric   case VK_VE_PC_LO32:
1525ffd83dbSDimitry Andric     return VE::fixup_ve_pc_lo32;
1535ffd83dbSDimitry Andric   case VK_VE_GOT_HI32:
1545ffd83dbSDimitry Andric     return VE::fixup_ve_got_hi32;
1555ffd83dbSDimitry Andric   case VK_VE_GOT_LO32:
1565ffd83dbSDimitry Andric     return VE::fixup_ve_got_lo32;
1575ffd83dbSDimitry Andric   case VK_VE_GOTOFF_HI32:
1585ffd83dbSDimitry Andric     return VE::fixup_ve_gotoff_hi32;
1595ffd83dbSDimitry Andric   case VK_VE_GOTOFF_LO32:
1605ffd83dbSDimitry Andric     return VE::fixup_ve_gotoff_lo32;
1615ffd83dbSDimitry Andric   case VK_VE_PLT_HI32:
1625ffd83dbSDimitry Andric     return VE::fixup_ve_plt_hi32;
1635ffd83dbSDimitry Andric   case VK_VE_PLT_LO32:
1645ffd83dbSDimitry Andric     return VE::fixup_ve_plt_lo32;
1655ffd83dbSDimitry Andric   case VK_VE_TLS_GD_HI32:
1665ffd83dbSDimitry Andric     return VE::fixup_ve_tls_gd_hi32;
1675ffd83dbSDimitry Andric   case VK_VE_TLS_GD_LO32:
1685ffd83dbSDimitry Andric     return VE::fixup_ve_tls_gd_lo32;
1695ffd83dbSDimitry Andric   case VK_VE_TPOFF_HI32:
1705ffd83dbSDimitry Andric     return VE::fixup_ve_tpoff_hi32;
1715ffd83dbSDimitry Andric   case VK_VE_TPOFF_LO32:
1725ffd83dbSDimitry Andric     return VE::fixup_ve_tpoff_lo32;
1735ffd83dbSDimitry Andric   }
1745ffd83dbSDimitry Andric }
1755ffd83dbSDimitry Andric 
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const176*0fca6ea1SDimitry Andric bool VEMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
1775ffd83dbSDimitry Andric                                          const MCFixup *Fixup) const {
178*0fca6ea1SDimitry Andric   if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup))
1790eae32dcSDimitry Andric     return false;
1800eae32dcSDimitry Andric 
1810eae32dcSDimitry Andric   Res =
1820eae32dcSDimitry Andric       MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
1830eae32dcSDimitry Andric 
1840eae32dcSDimitry Andric   return true;
1855ffd83dbSDimitry Andric }
1865ffd83dbSDimitry Andric 
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)1875ffd83dbSDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
1885ffd83dbSDimitry Andric   switch (Expr->getKind()) {
1895ffd83dbSDimitry Andric   case MCExpr::Target:
1905ffd83dbSDimitry Andric     llvm_unreachable("Can't handle nested target expr!");
1915ffd83dbSDimitry Andric     break;
1925ffd83dbSDimitry Andric 
1935ffd83dbSDimitry Andric   case MCExpr::Constant:
1945ffd83dbSDimitry Andric     break;
1955ffd83dbSDimitry Andric 
1965ffd83dbSDimitry Andric   case MCExpr::Binary: {
1975ffd83dbSDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
1985ffd83dbSDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
1995ffd83dbSDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
2005ffd83dbSDimitry Andric     break;
2015ffd83dbSDimitry Andric   }
2025ffd83dbSDimitry Andric 
2035ffd83dbSDimitry Andric   case MCExpr::SymbolRef: {
2045ffd83dbSDimitry Andric     // We're known to be under a TLS fixup, so any symbol should be
2055ffd83dbSDimitry Andric     // modified. There should be only one.
2065ffd83dbSDimitry Andric     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
2075ffd83dbSDimitry Andric     cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
2085ffd83dbSDimitry Andric     break;
2095ffd83dbSDimitry Andric   }
2105ffd83dbSDimitry Andric 
2115ffd83dbSDimitry Andric   case MCExpr::Unary:
2125ffd83dbSDimitry Andric     fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
2135ffd83dbSDimitry Andric     break;
2145ffd83dbSDimitry Andric   }
2155ffd83dbSDimitry Andric }
2165ffd83dbSDimitry Andric 
visitUsedExpr(MCStreamer & Streamer) const2175ffd83dbSDimitry Andric void VEMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
2185ffd83dbSDimitry Andric   Streamer.visitUsedExpr(*getSubExpr());
2195ffd83dbSDimitry Andric }
2205ffd83dbSDimitry Andric 
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const2215ffd83dbSDimitry Andric void VEMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
2225ffd83dbSDimitry Andric   switch (getKind()) {
2235ffd83dbSDimitry Andric   default:
2245ffd83dbSDimitry Andric     return;
2255ffd83dbSDimitry Andric   case VK_VE_TLS_GD_HI32:
2265ffd83dbSDimitry Andric   case VK_VE_TLS_GD_LO32:
2275ffd83dbSDimitry Andric   case VK_VE_TPOFF_HI32:
2285ffd83dbSDimitry Andric   case VK_VE_TPOFF_LO32:
2295ffd83dbSDimitry Andric     break;
2305ffd83dbSDimitry Andric   }
2315ffd83dbSDimitry Andric   fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
2325ffd83dbSDimitry Andric }
233