PPCMCExpr.cpp revision 263508
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
16using namespace llvm;
17
18const PPCMCExpr*
19PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
20                  bool isDarwin, MCContext &Ctx) {
21  return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
22}
23
24void 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
52bool
53PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
54                                     const MCAsmLayout *Layout) const {
55  MCValue Value;
56
57  if (!Layout || !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?
128static 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
153void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
154  AddValueSymbols_(getSubExpr(), Asm);
155}
156