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,
57                                      const MCFixup *Fixup) const {
58   MCValue Value;
59 
60   if (!getSubExpr()->EvaluateAsRelocatable(Value, Layout, Fixup))
61     return false;
62 
63   if (Value.isAbsolute()) {
64     int64_t Result = Value.getConstant();
65     switch (Kind) {
66       default:
67         llvm_unreachable("Invalid kind!");
68       case VK_PPC_LO:
69         Result = Result & 0xffff;
70         break;
71       case VK_PPC_HI:
72         Result = (Result >> 16) & 0xffff;
73         break;
74       case VK_PPC_HA:
75         Result = ((Result + 0x8000) >> 16) & 0xffff;
76         break;
77       case VK_PPC_HIGHER:
78         Result = (Result >> 32) & 0xffff;
79         break;
80       case VK_PPC_HIGHERA:
81         Result = ((Result + 0x8000) >> 32) & 0xffff;
82         break;
83       case VK_PPC_HIGHEST:
84         Result = (Result >> 48) & 0xffff;
85         break;
86       case VK_PPC_HIGHESTA:
87         Result = ((Result + 0x8000) >> 48) & 0xffff;
88         break;
89     }
90     Res = MCValue::get(Result);
91   } else {
92     if (!Layout)
93       return false;
94 
95     MCContext &Context = Layout->getAssembler().getContext();
96     const MCSymbolRefExpr *Sym = Value.getSymA();
97     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
98     if (Modifier != MCSymbolRefExpr::VK_None)
99       return false;
100     switch (Kind) {
101       default:
102         llvm_unreachable("Invalid kind!");
103       case VK_PPC_LO:
104         Modifier = MCSymbolRefExpr::VK_PPC_LO;
105         break;
106       case VK_PPC_HI:
107         Modifier = MCSymbolRefExpr::VK_PPC_HI;
108         break;
109       case VK_PPC_HA:
110         Modifier = MCSymbolRefExpr::VK_PPC_HA;
111         break;
112       case VK_PPC_HIGHERA:
113         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
114         break;
115       case VK_PPC_HIGHER:
116         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
117         break;
118       case VK_PPC_HIGHEST:
119         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
120         break;
121       case VK_PPC_HIGHESTA:
122         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
123         break;
124     }
125     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
126     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
127   }
128 
129   return true;
130 }
131 
132 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
133   Streamer.visitUsedExpr(*getSubExpr());
134 }
135