PPCMCExpr.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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
16using namespace llvm;
17
18#define DEBUG_TYPE "ppcmcexpr"
19
20const PPCMCExpr*
21PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
22                  bool isDarwin, MCContext &Ctx) {
23  return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
24}
25
26void 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
54bool
55PPCMCExpr::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
131void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
132  Streamer.visitUsedExpr(*getSubExpr());
133}
134