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 "PPCFixupKinds.h"
     11 #include "PPCMCExpr.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_HIGHER: OS << "@higher"; break;
     48     case VK_PPC_HIGHERA: OS << "@highera"; break;
     49     case VK_PPC_HIGHEST: OS << "@highest"; break;
     50     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
     51     }
     52   }
     53 }
     54 
     55 bool
     56 PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
     57   MCValue Value;
     58 
     59   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
     60     return false;
     61 
     62   if (!Value.isAbsolute())
     63     return false;
     64 
     65   Res = evaluateAsInt64(Value.getConstant());
     66   return true;
     67 }
     68 
     69 int64_t
     70 PPCMCExpr::evaluateAsInt64(int64_t Value) const {
     71   switch (Kind) {
     72     case VK_PPC_LO:
     73       return Value & 0xffff;
     74     case VK_PPC_HI:
     75       return (Value >> 16) & 0xffff;
     76     case VK_PPC_HA:
     77       return ((Value + 0x8000) >> 16) & 0xffff;
     78     case VK_PPC_HIGHER:
     79       return (Value >> 32) & 0xffff;
     80     case VK_PPC_HIGHERA:
     81       return ((Value + 0x8000) >> 32) & 0xffff;
     82     case VK_PPC_HIGHEST:
     83       return (Value >> 48) & 0xffff;
     84     case VK_PPC_HIGHESTA:
     85       return ((Value + 0x8000) >> 48) & 0xffff;
     86     case VK_PPC_None:
     87       break;
     88   }
     89   llvm_unreachable("Invalid kind!");
     90 }
     91 
     92 bool
     93 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
     94                                      const MCAsmLayout *Layout,
     95                                      const MCFixup *Fixup) const {
     96   MCValue Value;
     97 
     98   if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
     99     return false;
    100 
    101   if (Value.isAbsolute()) {
    102     int64_t Result = evaluateAsInt64(Value.getConstant());
    103     if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
    104         (Result >= 0x8000))
    105       return false;
    106     Res = MCValue::get(Result);
    107   } else {
    108     if (!Layout)
    109       return false;
    110 
    111     MCContext &Context = Layout->getAssembler().getContext();
    112     const MCSymbolRefExpr *Sym = Value.getSymA();
    113     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
    114     if (Modifier != MCSymbolRefExpr::VK_None)
    115       return false;
    116     switch (Kind) {
    117       default:
    118         llvm_unreachable("Invalid kind!");
    119       case VK_PPC_LO:
    120         Modifier = MCSymbolRefExpr::VK_PPC_LO;
    121         break;
    122       case VK_PPC_HI:
    123         Modifier = MCSymbolRefExpr::VK_PPC_HI;
    124         break;
    125       case VK_PPC_HA:
    126         Modifier = MCSymbolRefExpr::VK_PPC_HA;
    127         break;
    128       case VK_PPC_HIGHERA:
    129         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
    130         break;
    131       case VK_PPC_HIGHER:
    132         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
    133         break;
    134       case VK_PPC_HIGHEST:
    135         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
    136         break;
    137       case VK_PPC_HIGHESTA:
    138         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
    139         break;
    140     }
    141     Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
    142     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
    143   }
    144 
    145   return true;
    146 }
    147 
    148 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
    149   Streamer.visitUsedExpr(*getSubExpr());
    150 }
    151