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
17using namespace llvm;
18
19#define DEBUG_TYPE "ppcmcexpr"
20
21const PPCMCExpr*
22PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
23                  bool isDarwin, MCContext &Ctx) {
24  return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
25}
26
27void 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
55bool
56PPCMCExpr::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
69int64_t
70PPCMCExpr::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
92bool
93PPCMCExpr::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
148void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
149  Streamer.visitUsedExpr(*getSubExpr());
150}
151