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 "llvm/MC/MCAsmInfo.h"
     12 #include "llvm/MC/MCAssembler.h"
     13 #include "llvm/MC/MCContext.h"
     14 #include "llvm/MC/MCObjectStreamer.h"
     15 
     16 using namespace llvm;
     17 
     18 #define DEBUG_TYPE "ppcmcexpr"
     19 
     20 const PPCMCExpr*
     21 PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
     22                   bool isDarwin, MCContext &Ctx) {
     23   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
     24 }
     25 
     26 void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
     27   if (isDarwinSyntax()) {
     28     switch (Kind) {
     29     default: llvm_unreachable("Invalid kind!");
     30     case VK_PPC_LO: OS << "lo16"; break;
     31     case VK_PPC_HI: OS << "hi16"; break;
     32     case VK_PPC_HA: OS << "ha16"; break;
     33     }
     34 
     35     OS << '(';
     36     getSubExpr()->print(OS);
     37     OS << ')';
     38   } else {
     39     getSubExpr()->print(OS);
     40 
     41     switch (Kind) {
     42     default: llvm_unreachable("Invalid kind!");
     43     case VK_PPC_LO: OS << "@l"; break;
     44     case VK_PPC_HI: OS << "@h"; break;
     45     case VK_PPC_HA: OS << "@ha"; break;
     46     case VK_PPC_HIGHER: OS << "@higher"; break;
     47     case VK_PPC_HIGHERA: OS << "@highera"; break;
     48     case VK_PPC_HIGHEST: OS << "@highest"; break;
     49     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
     50     }
     51   }
     52 }
     53 
     54 bool
     55 PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     56                                      const MCAsmLayout *Layout) const {
     57   MCValue Value;
     58 
     59   if (!getSubExpr()->EvaluateAsRelocatable(Value, Layout))
     60     return false;
     61 
     62   if (Value.isAbsolute()) {
     63     int64_t Result = Value.getConstant();
     64     switch (Kind) {
     65       default:
     66         llvm_unreachable("Invalid kind!");
     67       case VK_PPC_LO:
     68         Result = Result & 0xffff;
     69         break;
     70       case VK_PPC_HI:
     71         Result = (Result >> 16) & 0xffff;
     72         break;
     73       case VK_PPC_HA:
     74         Result = ((Result + 0x8000) >> 16) & 0xffff;
     75         break;
     76       case VK_PPC_HIGHER:
     77         Result = (Result >> 32) & 0xffff;
     78         break;
     79       case VK_PPC_HIGHERA:
     80         Result = ((Result + 0x8000) >> 32) & 0xffff;
     81         break;
     82       case VK_PPC_HIGHEST:
     83         Result = (Result >> 48) & 0xffff;
     84         break;
     85       case VK_PPC_HIGHESTA:
     86         Result = ((Result + 0x8000) >> 48) & 0xffff;
     87         break;
     88     }
     89     Res = MCValue::get(Result);
     90   } else {
     91     if (!Layout)
     92       return false;
     93 
     94     MCContext &Context = Layout->getAssembler().getContext();
     95     const MCSymbolRefExpr *Sym = Value.getSymA();
     96     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
     97     if (Modifier != MCSymbolRefExpr::VK_None)
     98       return false;
     99     switch (Kind) {
    100       default:
    101         llvm_unreachable("Invalid kind!");
    102       case VK_PPC_LO:
    103         Modifier = MCSymbolRefExpr::VK_PPC_LO;
    104         break;
    105       case VK_PPC_HI:
    106         Modifier = MCSymbolRefExpr::VK_PPC_HI;
    107         break;
    108       case VK_PPC_HA:
    109         Modifier = MCSymbolRefExpr::VK_PPC_HA;
    110         break;
    111       case VK_PPC_HIGHERA:
    112         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
    113         break;
    114       case VK_PPC_HIGHER:
    115         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
    116         break;
    117       case VK_PPC_HIGHEST:
    118         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
    119         break;
    120       case VK_PPC_HIGHESTA:
    121         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
    122         break;
    123     }
    124     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
    125     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
    126   }
    127 
    128   return true;
    129 }
    130 
    131 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
    132   Streamer.visitUsedExpr(*getSubExpr());
    133 }
    134