Home | History | Annotate | Line # | Download | only in MCTargetDesc
      1 //===-- MipsMCExpr.cpp - Mips specific MC expression classes --------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "MipsMCExpr.h"
     10 #include "llvm/BinaryFormat/ELF.h"
     11 #include "llvm/MC/MCAsmInfo.h"
     12 #include "llvm/MC/MCAssembler.h"
     13 #include "llvm/MC/MCContext.h"
     14 #include "llvm/MC/MCStreamer.h"
     15 #include "llvm/MC/MCSymbolELF.h"
     16 #include "llvm/MC/MCValue.h"
     17 #include "llvm/Support/Casting.h"
     18 #include "llvm/Support/ErrorHandling.h"
     19 #include "llvm/Support/MathExtras.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include <cstdint>
     22 
     23 using namespace llvm;
     24 
     25 #define DEBUG_TYPE "mipsmcexpr"
     26 
     27 const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind,
     28                                      const MCExpr *Expr, MCContext &Ctx) {
     29   return new (Ctx) MipsMCExpr(Kind, Expr);
     30 }
     31 
     32 const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind,
     33                                           const MCExpr *Expr, MCContext &Ctx) {
     34   return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx);
     35 }
     36 
     37 void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
     38   int64_t AbsVal;
     39 
     40   switch (Kind) {
     41   case MEK_None:
     42   case MEK_Special:
     43     llvm_unreachable("MEK_None and MEK_Special are invalid");
     44     break;
     45   case MEK_DTPREL:
     46     // MEK_DTPREL is used for marking TLS DIEExpr only
     47     // and contains a regular sub-expression.
     48     getSubExpr()->print(OS, MAI, true);
     49     return;
     50   case MEK_CALL_HI16:
     51     OS << "%call_hi";
     52     break;
     53   case MEK_CALL_LO16:
     54     OS << "%call_lo";
     55     break;
     56   case MEK_DTPREL_HI:
     57     OS << "%dtprel_hi";
     58     break;
     59   case MEK_DTPREL_LO:
     60     OS << "%dtprel_lo";
     61     break;
     62   case MEK_GOT:
     63     OS << "%got";
     64     break;
     65   case MEK_GOTTPREL:
     66     OS << "%gottprel";
     67     break;
     68   case MEK_GOT_CALL:
     69     OS << "%call16";
     70     break;
     71   case MEK_GOT_DISP:
     72     OS << "%got_disp";
     73     break;
     74   case MEK_GOT_HI16:
     75     OS << "%got_hi";
     76     break;
     77   case MEK_GOT_LO16:
     78     OS << "%got_lo";
     79     break;
     80   case MEK_GOT_PAGE:
     81     OS << "%got_page";
     82     break;
     83   case MEK_GOT_OFST:
     84     OS << "%got_ofst";
     85     break;
     86   case MEK_GPREL:
     87     OS << "%gp_rel";
     88     break;
     89   case MEK_HI:
     90     OS << "%hi";
     91     break;
     92   case MEK_HIGHER:
     93     OS << "%higher";
     94     break;
     95   case MEK_HIGHEST:
     96     OS << "%highest";
     97     break;
     98   case MEK_LO:
     99     OS << "%lo";
    100     break;
    101   case MEK_NEG:
    102     OS << "%neg";
    103     break;
    104   case MEK_PCREL_HI16:
    105     OS << "%pcrel_hi";
    106     break;
    107   case MEK_PCREL_LO16:
    108     OS << "%pcrel_lo";
    109     break;
    110   case MEK_TLSGD:
    111     OS << "%tlsgd";
    112     break;
    113   case MEK_TLSLDM:
    114     OS << "%tlsldm";
    115     break;
    116   case MEK_TPREL_HI:
    117     OS << "%tprel_hi";
    118     break;
    119   case MEK_TPREL_LO:
    120     OS << "%tprel_lo";
    121     break;
    122   }
    123 
    124   OS << '(';
    125   if (Expr->evaluateAsAbsolute(AbsVal))
    126     OS << AbsVal;
    127   else
    128     Expr->print(OS, MAI, true);
    129   OS << ')';
    130 }
    131 
    132 bool
    133 MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
    134                                       const MCAsmLayout *Layout,
    135                                       const MCFixup *Fixup) const {
    136   // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
    137   if (isGpOff()) {
    138     const MCExpr *SubExpr =
    139         cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr())
    140             ->getSubExpr();
    141     if (!SubExpr->evaluateAsRelocatable(Res, Layout, Fixup))
    142       return false;
    143 
    144     Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
    145                        MEK_Special);
    146     return true;
    147   }
    148 
    149   if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
    150     return false;
    151 
    152   if (Res.getRefKind() != MCSymbolRefExpr::VK_None)
    153     return false;
    154 
    155   // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
    156   // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
    157   // caller.
    158   if (Res.isAbsolute() && Fixup == nullptr) {
    159     int64_t AbsVal = Res.getConstant();
    160     switch (Kind) {
    161     case MEK_None:
    162     case MEK_Special:
    163       llvm_unreachable("MEK_None and MEK_Special are invalid");
    164     case MEK_DTPREL:
    165       // MEK_DTPREL is used for marking TLS DIEExpr only
    166       // and contains a regular sub-expression.
    167       return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
    168     case MEK_DTPREL_HI:
    169     case MEK_DTPREL_LO:
    170     case MEK_GOT:
    171     case MEK_GOTTPREL:
    172     case MEK_GOT_CALL:
    173     case MEK_GOT_DISP:
    174     case MEK_GOT_HI16:
    175     case MEK_GOT_LO16:
    176     case MEK_GOT_OFST:
    177     case MEK_GOT_PAGE:
    178     case MEK_GPREL:
    179     case MEK_PCREL_HI16:
    180     case MEK_PCREL_LO16:
    181     case MEK_TLSGD:
    182     case MEK_TLSLDM:
    183     case MEK_TPREL_HI:
    184     case MEK_TPREL_LO:
    185       return false;
    186     case MEK_LO:
    187     case MEK_CALL_LO16:
    188       AbsVal = SignExtend64<16>(AbsVal);
    189       break;
    190     case MEK_CALL_HI16:
    191     case MEK_HI:
    192       AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16);
    193       break;
    194     case MEK_HIGHER:
    195       AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32);
    196       break;
    197     case MEK_HIGHEST:
    198       AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48);
    199       break;
    200     case MEK_NEG:
    201       AbsVal = -AbsVal;
    202       break;
    203     }
    204     Res = MCValue::get(AbsVal);
    205     return true;
    206   }
    207 
    208   // We want to defer it for relocatable expressions since the constant is
    209   // applied to the whole symbol value.
    210   //
    211   // The value of getKind() that is given to MCValue is only intended to aid
    212   // debugging when inspecting MCValue objects. It shouldn't be relied upon
    213   // for decision making.
    214   Res =
    215       MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
    216 
    217   return true;
    218 }
    219 
    220 void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
    221   Streamer.visitUsedExpr(*getSubExpr());
    222 }
    223 
    224 static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
    225   switch (Expr->getKind()) {
    226   case MCExpr::Target:
    227     fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm);
    228     break;
    229   case MCExpr::Constant:
    230     break;
    231   case MCExpr::Binary: {
    232     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
    233     fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
    234     fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
    235     break;
    236   }
    237   case MCExpr::SymbolRef: {
    238     // We're known to be under a TLS fixup, so any symbol should be
    239     // modified. There should be only one.
    240     const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
    241     cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
    242     break;
    243   }
    244   case MCExpr::Unary:
    245     fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
    246     break;
    247   }
    248 }
    249 
    250 void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
    251   switch (getKind()) {
    252   case MEK_None:
    253   case MEK_Special:
    254     llvm_unreachable("MEK_None and MEK_Special are invalid");
    255     break;
    256   case MEK_CALL_HI16:
    257   case MEK_CALL_LO16:
    258   case MEK_GOT:
    259   case MEK_GOT_CALL:
    260   case MEK_GOT_DISP:
    261   case MEK_GOT_HI16:
    262   case MEK_GOT_LO16:
    263   case MEK_GOT_OFST:
    264   case MEK_GOT_PAGE:
    265   case MEK_GPREL:
    266   case MEK_HI:
    267   case MEK_HIGHER:
    268   case MEK_HIGHEST:
    269   case MEK_LO:
    270   case MEK_NEG:
    271   case MEK_PCREL_HI16:
    272   case MEK_PCREL_LO16:
    273     // If we do have nested target-specific expressions, they will be in
    274     // a consecutive chain.
    275     if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
    276       E->fixELFSymbolsInTLSFixups(Asm);
    277     break;
    278   case MEK_DTPREL:
    279   case MEK_DTPREL_HI:
    280   case MEK_DTPREL_LO:
    281   case MEK_TLSLDM:
    282   case MEK_TLSGD:
    283   case MEK_GOTTPREL:
    284   case MEK_TPREL_HI:
    285   case MEK_TPREL_LO:
    286     fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
    287     break;
    288   }
    289 }
    290 
    291 bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const {
    292   if (getKind() == MEK_HI || getKind() == MEK_LO) {
    293     if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) {
    294       if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) {
    295         if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) {
    296           Kind = getKind();
    297           return true;
    298         }
    299       }
    300     }
    301   }
    302   return false;
    303 }
    304