Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "PPCMCExpr.h"
     11 #include "PPCFixupKinds.h"
     12 #include "llvm/MC/MCAsmInfo.h"
     13 #include "llvm/MC/MCAssembler.h"
     14 #include "llvm/MC/MCContext.h"
     15 #include "llvm/MC/MCObjectStreamer.h"
     16 
     17 using namespace llvm;
     18 
     19 #define DEBUG_TYPE "ppcmcexpr"
     20 
     21 const PPCMCExpr*
     22 PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
     23                   bool isDarwin, MCContext &Ctx) {
     24   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
     25 }
     26 
     27 void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
     28   if (isDarwinSyntax()) {
     29     switch (Kind) {
     30     default: llvm_unreachable("Invalid kind!");
     31     case VK_PPC_LO: OS << "lo16"; break;
     32     case VK_PPC_HI: OS << "hi16"; break;
     33     case VK_PPC_HA: OS << "ha16"; break;
     34     }
     35 
     36     OS << '(';
     37     getSubExpr()->print(OS, MAI);
     38     OS << ')';
     39   } else {
     40     getSubExpr()->print(OS, MAI);
     41 
     42     switch (Kind) {
     43     default: llvm_unreachable("Invalid kind!");
     44     case VK_PPC_LO: OS << "@l"; break;
     45     case VK_PPC_HI: OS << "@h"; break;
     46     case VK_PPC_HA: OS << "@ha"; break;
     47     case VK_PPC_HIGH: OS << "@high"; break;
     48     case VK_PPC_HIGHA: OS << "@higha"; break;
     49     case VK_PPC_HIGHER: OS << "@higher"; break;
     50     case VK_PPC_HIGHERA: OS << "@highera"; break;
     51     case VK_PPC_HIGHEST: OS << "@highest"; break;
     52     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
     53     }
     54   }
     55 }
     56 
     57 bool
     58 PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
     59   MCValue Value;
     60 
     61   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
     62     return false;
     63 
     64   if (!Value.isAbsolute())
     65     return false;
     66 
     67   Res = evaluateAsInt64(Value.getConstant());
     68   return true;
     69 }
     70 
     71 int64_t
     72 PPCMCExpr::evaluateAsInt64(int64_t Value) const {
     73   switch (Kind) {
     74     case VK_PPC_LO:
     75       return Value & 0xffff;
     76     case VK_PPC_HI:
     77       return (Value >> 16) & 0xffff;
     78     case VK_PPC_HA:
     79       return ((Value + 0x8000) >> 16) & 0xffff;
     80     case VK_PPC_HIGH:
     81       return (Value >> 16) & 0xffff;
     82     case VK_PPC_HIGHA:
     83       return ((Value + 0x8000) >> 16) & 0xffff;
     84     case VK_PPC_HIGHER:
     85       return (Value >> 32) & 0xffff;
     86     case VK_PPC_HIGHERA:
     87       return ((Value + 0x8000) >> 32) & 0xffff;
     88     case VK_PPC_HIGHEST:
     89       return (Value >> 48) & 0xffff;
     90     case VK_PPC_HIGHESTA:
     91       return ((Value + 0x8000) >> 48) & 0xffff;
     92     case VK_PPC_None:
     93       break;
     94   }
     95   llvm_unreachable("Invalid kind!");
     96 }
     97 
     98 bool
     99 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
    100                                      const MCAsmLayout *Layout,
    101                                      const MCFixup *Fixup) const {
    102   MCValue Value;
    103 
    104   if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
    105     return false;
    106 
    107   if (Value.isAbsolute()) {
    108     int64_t Result = evaluateAsInt64(Value.getConstant());
    109     if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
    110         (Result >= 0x8000))
    111       return false;
    112     Res = MCValue::get(Result);
    113   } else {
    114     if (!Layout)
    115       return false;
    116 
    117     MCContext &Context = Layout->getAssembler().getContext();
    118     const MCSymbolRefExpr *Sym = Value.getSymA();
    119     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
    120     if (Modifier != MCSymbolRefExpr::VK_None)
    121       return false;
    122     switch (Kind) {
    123       default:
    124         llvm_unreachable("Invalid kind!");
    125       case VK_PPC_LO:
    126         Modifier = MCSymbolRefExpr::VK_PPC_LO;
    127         break;
    128       case VK_PPC_HI:
    129         Modifier = MCSymbolRefExpr::VK_PPC_HI;
    130         break;
    131       case VK_PPC_HA:
    132         Modifier = MCSymbolRefExpr::VK_PPC_HA;
    133         break;
    134       case VK_PPC_HIGH:
    135         Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
    136         break;
    137       case VK_PPC_HIGHA:
    138         Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
    139         break;
    140       case VK_PPC_HIGHERA:
    141         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
    142         break;
    143       case VK_PPC_HIGHER:
    144         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
    145         break;
    146       case VK_PPC_HIGHEST:
    147         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
    148         break;
    149       case VK_PPC_HIGHESTA:
    150         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
    151         break;
    152     }
    153     Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
    154     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
    155   }
    156 
    157   return true;
    158 }
    159 
    160 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
    161   Streamer.visitUsedExpr(*getSubExpr());
    162 }
    163