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 #define DEBUG_TYPE "ppcmcexpr"
     11 #include "PPCMCExpr.h"
     12 #include "llvm/MC/MCAssembler.h"
     13 #include "llvm/MC/MCContext.h"
     14 #include "llvm/MC/MCAsmInfo.h"
     15 
     16 using namespace llvm;
     17 
     18 const PPCMCExpr*
     19 PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
     20                   bool isDarwin, MCContext &Ctx) {
     21   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
     22 }
     23 
     24 void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
     25   if (isDarwinSyntax()) {
     26     switch (Kind) {
     27     default: llvm_unreachable("Invalid kind!");
     28     case VK_PPC_LO: OS << "lo16"; break;
     29     case VK_PPC_HI: OS << "hi16"; break;
     30     case VK_PPC_HA: OS << "ha16"; break;
     31     }
     32 
     33     OS << '(';
     34     getSubExpr()->print(OS);
     35     OS << ')';
     36   } else {
     37     getSubExpr()->print(OS);
     38 
     39     switch (Kind) {
     40     default: llvm_unreachable("Invalid kind!");
     41     case VK_PPC_LO: OS << "@l"; break;
     42     case VK_PPC_HI: OS << "@h"; break;
     43     case VK_PPC_HA: OS << "@ha"; break;
     44     case VK_PPC_HIGHER: OS << "@higher"; break;
     45     case VK_PPC_HIGHERA: OS << "@highera"; break;
     46     case VK_PPC_HIGHEST: OS << "@highest"; break;
     47     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
     48     }
     49   }
     50 }
     51 
     52 bool
     53 PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
     54                                      const MCAsmLayout *Layout) const {
     55   MCValue Value;
     56 
     57   if (!getSubExpr()->EvaluateAsRelocatable(Value, *Layout))
     58     return false;
     59 
     60   if (Value.isAbsolute()) {
     61     int64_t Result = Value.getConstant();
     62     switch (Kind) {
     63       default:
     64         llvm_unreachable("Invalid kind!");
     65       case VK_PPC_LO:
     66         Result = Result & 0xffff;
     67         break;
     68       case VK_PPC_HI:
     69         Result = (Result >> 16) & 0xffff;
     70         break;
     71       case VK_PPC_HA:
     72         Result = ((Result + 0x8000) >> 16) & 0xffff;
     73         break;
     74       case VK_PPC_HIGHER:
     75         Result = (Result >> 32) & 0xffff;
     76         break;
     77       case VK_PPC_HIGHERA:
     78         Result = ((Result + 0x8000) >> 32) & 0xffff;
     79         break;
     80       case VK_PPC_HIGHEST:
     81         Result = (Result >> 48) & 0xffff;
     82         break;
     83       case VK_PPC_HIGHESTA:
     84         Result = ((Result + 0x8000) >> 48) & 0xffff;
     85         break;
     86     }
     87     Res = MCValue::get(Result);
     88   } else {
     89     MCContext &Context = Layout->getAssembler().getContext();
     90     const MCSymbolRefExpr *Sym = Value.getSymA();
     91     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
     92     if (Modifier != MCSymbolRefExpr::VK_None)
     93       return false;
     94     switch (Kind) {
     95       default:
     96         llvm_unreachable("Invalid kind!");
     97       case VK_PPC_LO:
     98         Modifier = MCSymbolRefExpr::VK_PPC_LO;
     99         break;
    100       case VK_PPC_HI:
    101         Modifier = MCSymbolRefExpr::VK_PPC_HI;
    102         break;
    103       case VK_PPC_HA:
    104         Modifier = MCSymbolRefExpr::VK_PPC_HA;
    105         break;
    106       case VK_PPC_HIGHERA:
    107         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
    108         break;
    109       case VK_PPC_HIGHER:
    110         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
    111         break;
    112       case VK_PPC_HIGHEST:
    113         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
    114         break;
    115       case VK_PPC_HIGHESTA:
    116         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
    117         break;
    118     }
    119     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
    120     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
    121   }
    122 
    123   return true;
    124 }
    125 
    126 // FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
    127 // that method should be made public?
    128 static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
    129   switch (Value->getKind()) {
    130   case MCExpr::Target:
    131     llvm_unreachable("Can't handle nested target expr!");
    132 
    133   case MCExpr::Constant:
    134     break;
    135 
    136   case MCExpr::Binary: {
    137     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
    138     AddValueSymbols_(BE->getLHS(), Asm);
    139     AddValueSymbols_(BE->getRHS(), Asm);
    140     break;
    141   }
    142 
    143   case MCExpr::SymbolRef:
    144     Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
    145     break;
    146 
    147   case MCExpr::Unary:
    148     AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
    149     break;
    150   }
    151 }
    152 
    153 void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
    154   AddValueSymbols_(getSubExpr(), Asm);
    155 }
    156