xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- MipsMCExpr.cpp - Mips 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 #include "MipsMCExpr.h"
100b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
110b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
170b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
180b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
190b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <cstdint>
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define DEBUG_TYPE "mipsmcexpr"
260b57cec5SDimitry Andric 
create(MipsMCExpr::MipsExprKind Kind,const MCExpr * Expr,MCContext & Ctx)270b57cec5SDimitry Andric const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind,
280b57cec5SDimitry Andric                                      const MCExpr *Expr, MCContext &Ctx) {
290b57cec5SDimitry Andric   return new (Ctx) MipsMCExpr(Kind, Expr);
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric 
createGpOff(MipsMCExpr::MipsExprKind Kind,const MCExpr * Expr,MCContext & Ctx)320b57cec5SDimitry Andric const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind,
330b57cec5SDimitry Andric                                           const MCExpr *Expr, MCContext &Ctx) {
340b57cec5SDimitry Andric   return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx);
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const370b57cec5SDimitry Andric void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
380b57cec5SDimitry Andric   int64_t AbsVal;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   switch (Kind) {
410b57cec5SDimitry Andric   case MEK_None:
420b57cec5SDimitry Andric   case MEK_Special:
430b57cec5SDimitry Andric     llvm_unreachable("MEK_None and MEK_Special are invalid");
440b57cec5SDimitry Andric     break;
450b57cec5SDimitry Andric   case MEK_DTPREL:
460b57cec5SDimitry Andric     // MEK_DTPREL is used for marking TLS DIEExpr only
470b57cec5SDimitry Andric     // and contains a regular sub-expression.
480b57cec5SDimitry Andric     getSubExpr()->print(OS, MAI, true);
490b57cec5SDimitry Andric     return;
500b57cec5SDimitry Andric   case MEK_CALL_HI16:
510b57cec5SDimitry Andric     OS << "%call_hi";
520b57cec5SDimitry Andric     break;
530b57cec5SDimitry Andric   case MEK_CALL_LO16:
540b57cec5SDimitry Andric     OS << "%call_lo";
550b57cec5SDimitry Andric     break;
560b57cec5SDimitry Andric   case MEK_DTPREL_HI:
570b57cec5SDimitry Andric     OS << "%dtprel_hi";
580b57cec5SDimitry Andric     break;
590b57cec5SDimitry Andric   case MEK_DTPREL_LO:
600b57cec5SDimitry Andric     OS << "%dtprel_lo";
610b57cec5SDimitry Andric     break;
620b57cec5SDimitry Andric   case MEK_GOT:
630b57cec5SDimitry Andric     OS << "%got";
640b57cec5SDimitry Andric     break;
650b57cec5SDimitry Andric   case MEK_GOTTPREL:
660b57cec5SDimitry Andric     OS << "%gottprel";
670b57cec5SDimitry Andric     break;
680b57cec5SDimitry Andric   case MEK_GOT_CALL:
690b57cec5SDimitry Andric     OS << "%call16";
700b57cec5SDimitry Andric     break;
710b57cec5SDimitry Andric   case MEK_GOT_DISP:
720b57cec5SDimitry Andric     OS << "%got_disp";
730b57cec5SDimitry Andric     break;
740b57cec5SDimitry Andric   case MEK_GOT_HI16:
750b57cec5SDimitry Andric     OS << "%got_hi";
760b57cec5SDimitry Andric     break;
770b57cec5SDimitry Andric   case MEK_GOT_LO16:
780b57cec5SDimitry Andric     OS << "%got_lo";
790b57cec5SDimitry Andric     break;
800b57cec5SDimitry Andric   case MEK_GOT_PAGE:
810b57cec5SDimitry Andric     OS << "%got_page";
820b57cec5SDimitry Andric     break;
830b57cec5SDimitry Andric   case MEK_GOT_OFST:
840b57cec5SDimitry Andric     OS << "%got_ofst";
850b57cec5SDimitry Andric     break;
860b57cec5SDimitry Andric   case MEK_GPREL:
870b57cec5SDimitry Andric     OS << "%gp_rel";
880b57cec5SDimitry Andric     break;
890b57cec5SDimitry Andric   case MEK_HI:
900b57cec5SDimitry Andric     OS << "%hi";
910b57cec5SDimitry Andric     break;
920b57cec5SDimitry Andric   case MEK_HIGHER:
930b57cec5SDimitry Andric     OS << "%higher";
940b57cec5SDimitry Andric     break;
950b57cec5SDimitry Andric   case MEK_HIGHEST:
960b57cec5SDimitry Andric     OS << "%highest";
970b57cec5SDimitry Andric     break;
980b57cec5SDimitry Andric   case MEK_LO:
990b57cec5SDimitry Andric     OS << "%lo";
1000b57cec5SDimitry Andric     break;
1010b57cec5SDimitry Andric   case MEK_NEG:
1020b57cec5SDimitry Andric     OS << "%neg";
1030b57cec5SDimitry Andric     break;
1040b57cec5SDimitry Andric   case MEK_PCREL_HI16:
1050b57cec5SDimitry Andric     OS << "%pcrel_hi";
1060b57cec5SDimitry Andric     break;
1070b57cec5SDimitry Andric   case MEK_PCREL_LO16:
1080b57cec5SDimitry Andric     OS << "%pcrel_lo";
1090b57cec5SDimitry Andric     break;
1100b57cec5SDimitry Andric   case MEK_TLSGD:
1110b57cec5SDimitry Andric     OS << "%tlsgd";
1120b57cec5SDimitry Andric     break;
1130b57cec5SDimitry Andric   case MEK_TLSLDM:
1140b57cec5SDimitry Andric     OS << "%tlsldm";
1150b57cec5SDimitry Andric     break;
1160b57cec5SDimitry Andric   case MEK_TPREL_HI:
1170b57cec5SDimitry Andric     OS << "%tprel_hi";
1180b57cec5SDimitry Andric     break;
1190b57cec5SDimitry Andric   case MEK_TPREL_LO:
1200b57cec5SDimitry Andric     OS << "%tprel_lo";
1210b57cec5SDimitry Andric     break;
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   OS << '(';
1250b57cec5SDimitry Andric   if (Expr->evaluateAsAbsolute(AbsVal))
1260b57cec5SDimitry Andric     OS << AbsVal;
1270b57cec5SDimitry Andric   else
1280b57cec5SDimitry Andric     Expr->print(OS, MAI, true);
1290b57cec5SDimitry Andric   OS << ')';
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
evaluateAsRelocatableImpl(MCValue & Res,const MCAssembler * Asm,const MCFixup * Fixup) const132*0fca6ea1SDimitry Andric bool MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
1330b57cec5SDimitry Andric                                            const MCFixup *Fixup) const {
1340b57cec5SDimitry Andric   // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
1350b57cec5SDimitry Andric   if (isGpOff()) {
1360b57cec5SDimitry Andric     const MCExpr *SubExpr =
1370b57cec5SDimitry Andric         cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr())
1380b57cec5SDimitry Andric             ->getSubExpr();
139*0fca6ea1SDimitry Andric     if (!SubExpr->evaluateAsRelocatable(Res, Asm, Fixup))
1400b57cec5SDimitry Andric       return false;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
1430b57cec5SDimitry Andric                        MEK_Special);
1440b57cec5SDimitry Andric     return true;
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
147*0fca6ea1SDimitry Andric   if (!getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup))
1480b57cec5SDimitry Andric     return false;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   if (Res.getRefKind() != MCSymbolRefExpr::VK_None)
1510b57cec5SDimitry Andric     return false;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
1540b57cec5SDimitry Andric   // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
1550b57cec5SDimitry Andric   // caller.
1560b57cec5SDimitry Andric   if (Res.isAbsolute() && Fixup == nullptr) {
1570b57cec5SDimitry Andric     int64_t AbsVal = Res.getConstant();
1580b57cec5SDimitry Andric     switch (Kind) {
1590b57cec5SDimitry Andric     case MEK_None:
1600b57cec5SDimitry Andric     case MEK_Special:
1610b57cec5SDimitry Andric       llvm_unreachable("MEK_None and MEK_Special are invalid");
1620b57cec5SDimitry Andric     case MEK_DTPREL:
1630b57cec5SDimitry Andric       // MEK_DTPREL is used for marking TLS DIEExpr only
1640b57cec5SDimitry Andric       // and contains a regular sub-expression.
165*0fca6ea1SDimitry Andric       return getSubExpr()->evaluateAsRelocatable(Res, Asm, Fixup);
1660b57cec5SDimitry Andric     case MEK_DTPREL_HI:
1670b57cec5SDimitry Andric     case MEK_DTPREL_LO:
1680b57cec5SDimitry Andric     case MEK_GOT:
1690b57cec5SDimitry Andric     case MEK_GOTTPREL:
1700b57cec5SDimitry Andric     case MEK_GOT_CALL:
1710b57cec5SDimitry Andric     case MEK_GOT_DISP:
1720b57cec5SDimitry Andric     case MEK_GOT_HI16:
1730b57cec5SDimitry Andric     case MEK_GOT_LO16:
1740b57cec5SDimitry Andric     case MEK_GOT_OFST:
1750b57cec5SDimitry Andric     case MEK_GOT_PAGE:
1760b57cec5SDimitry Andric     case MEK_GPREL:
1770b57cec5SDimitry Andric     case MEK_PCREL_HI16:
1780b57cec5SDimitry Andric     case MEK_PCREL_LO16:
1790b57cec5SDimitry Andric     case MEK_TLSGD:
1800b57cec5SDimitry Andric     case MEK_TLSLDM:
1810b57cec5SDimitry Andric     case MEK_TPREL_HI:
1820b57cec5SDimitry Andric     case MEK_TPREL_LO:
1830b57cec5SDimitry Andric       return false;
1840b57cec5SDimitry Andric     case MEK_LO:
1850b57cec5SDimitry Andric     case MEK_CALL_LO16:
1860b57cec5SDimitry Andric       AbsVal = SignExtend64<16>(AbsVal);
1870b57cec5SDimitry Andric       break;
1880b57cec5SDimitry Andric     case MEK_CALL_HI16:
1890b57cec5SDimitry Andric     case MEK_HI:
1900b57cec5SDimitry Andric       AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16);
1910b57cec5SDimitry Andric       break;
1920b57cec5SDimitry Andric     case MEK_HIGHER:
1930b57cec5SDimitry Andric       AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32);
1940b57cec5SDimitry Andric       break;
1950b57cec5SDimitry Andric     case MEK_HIGHEST:
1960b57cec5SDimitry Andric       AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48);
1970b57cec5SDimitry Andric       break;
1980b57cec5SDimitry Andric     case MEK_NEG:
1990b57cec5SDimitry Andric       AbsVal = -AbsVal;
2000b57cec5SDimitry Andric       break;
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric     Res = MCValue::get(AbsVal);
2030b57cec5SDimitry Andric     return true;
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   // We want to defer it for relocatable expressions since the constant is
2070b57cec5SDimitry Andric   // applied to the whole symbol value.
2080b57cec5SDimitry Andric   //
2090b57cec5SDimitry Andric   // The value of getKind() that is given to MCValue is only intended to aid
2100b57cec5SDimitry Andric   // debugging when inspecting MCValue objects. It shouldn't be relied upon
2110b57cec5SDimitry Andric   // for decision making.
212480093f4SDimitry Andric   Res =
213480093f4SDimitry Andric       MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   return true;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
visitUsedExpr(MCStreamer & Streamer) const2180b57cec5SDimitry Andric void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
2190b57cec5SDimitry Andric   Streamer.visitUsedExpr(*getSubExpr());
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric 
fixELFSymbolsInTLSFixupsImpl(const MCExpr * Expr,MCAssembler & Asm)2220b57cec5SDimitry Andric static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
2230b57cec5SDimitry Andric   switch (Expr->getKind()) {
2240b57cec5SDimitry Andric   case MCExpr::Target:
2250b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm);
2260b57cec5SDimitry Andric     break;
2270b57cec5SDimitry Andric   case MCExpr::Constant:
2280b57cec5SDimitry Andric     break;
2290b57cec5SDimitry Andric   case MCExpr::Binary: {
2300b57cec5SDimitry Andric     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
2310b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
2320b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
2330b57cec5SDimitry Andric     break;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric   case MCExpr::SymbolRef: {
2360b57cec5SDimitry Andric     // We're known to be under a TLS fixup, so any symbol should be
2370b57cec5SDimitry Andric     // modified. There should be only one.
2380b57cec5SDimitry Andric     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
2390b57cec5SDimitry Andric     cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
2400b57cec5SDimitry Andric     break;
2410b57cec5SDimitry Andric   }
2420b57cec5SDimitry Andric   case MCExpr::Unary:
2430b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
2440b57cec5SDimitry Andric     break;
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
fixELFSymbolsInTLSFixups(MCAssembler & Asm) const2480b57cec5SDimitry Andric void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
2490b57cec5SDimitry Andric   switch (getKind()) {
2500b57cec5SDimitry Andric   case MEK_None:
2510b57cec5SDimitry Andric   case MEK_Special:
2520b57cec5SDimitry Andric     llvm_unreachable("MEK_None and MEK_Special are invalid");
2530b57cec5SDimitry Andric     break;
2540b57cec5SDimitry Andric   case MEK_CALL_HI16:
2550b57cec5SDimitry Andric   case MEK_CALL_LO16:
2560b57cec5SDimitry Andric   case MEK_GOT:
2570b57cec5SDimitry Andric   case MEK_GOT_CALL:
2580b57cec5SDimitry Andric   case MEK_GOT_DISP:
2590b57cec5SDimitry Andric   case MEK_GOT_HI16:
2600b57cec5SDimitry Andric   case MEK_GOT_LO16:
2610b57cec5SDimitry Andric   case MEK_GOT_OFST:
2620b57cec5SDimitry Andric   case MEK_GOT_PAGE:
2630b57cec5SDimitry Andric   case MEK_GPREL:
2640b57cec5SDimitry Andric   case MEK_HI:
2650b57cec5SDimitry Andric   case MEK_HIGHER:
2660b57cec5SDimitry Andric   case MEK_HIGHEST:
2670b57cec5SDimitry Andric   case MEK_LO:
2680b57cec5SDimitry Andric   case MEK_NEG:
2690b57cec5SDimitry Andric   case MEK_PCREL_HI16:
2700b57cec5SDimitry Andric   case MEK_PCREL_LO16:
2710b57cec5SDimitry Andric     // If we do have nested target-specific expressions, they will be in
2720b57cec5SDimitry Andric     // a consecutive chain.
2730b57cec5SDimitry Andric     if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
2740b57cec5SDimitry Andric       E->fixELFSymbolsInTLSFixups(Asm);
2750b57cec5SDimitry Andric     break;
2760b57cec5SDimitry Andric   case MEK_DTPREL:
2770b57cec5SDimitry Andric   case MEK_DTPREL_HI:
2780b57cec5SDimitry Andric   case MEK_DTPREL_LO:
2790b57cec5SDimitry Andric   case MEK_TLSLDM:
2800b57cec5SDimitry Andric   case MEK_TLSGD:
2810b57cec5SDimitry Andric   case MEK_GOTTPREL:
2820b57cec5SDimitry Andric   case MEK_TPREL_HI:
2830b57cec5SDimitry Andric   case MEK_TPREL_LO:
2840b57cec5SDimitry Andric     fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric 
isGpOff(MipsExprKind & Kind) const2890b57cec5SDimitry Andric bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const {
2900b57cec5SDimitry Andric   if (getKind() == MEK_HI || getKind() == MEK_LO) {
2910b57cec5SDimitry Andric     if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) {
2920b57cec5SDimitry Andric       if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) {
2930b57cec5SDimitry Andric         if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) {
2940b57cec5SDimitry Andric           Kind = getKind();
2950b57cec5SDimitry Andric           return true;
2960b57cec5SDimitry Andric         }
2970b57cec5SDimitry Andric       }
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric   return false;
3010b57cec5SDimitry Andric }
302