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 "PPCFixupKinds.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
17 using namespace llvm;
18
19 #define DEBUG_TYPE "ppcmcexpr"
20
21 const PPCMCExpr*
create(VariantKind Kind,const MCExpr * Expr,bool isDarwin,MCContext & Ctx)22 PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
23 bool isDarwin, MCContext &Ctx) {
24 return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
25 }
26
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const27 void 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_HIGH: OS << "@high"; break;
48 case VK_PPC_HIGHA: OS << "@higha"; break;
49 case VK_PPC_HIGHER: OS << "@higher"; break;
50 case VK_PPC_HIGHERA: OS << "@highera"; break;
51 case VK_PPC_HIGHEST: OS << "@highest"; break;
52 case VK_PPC_HIGHESTA: OS << "@highesta"; break;
53 }
54 }
55 }
56
57 bool
evaluateAsConstant(int64_t & Res) const58 PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
59 MCValue Value;
60
61 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
62 return false;
63
64 if (!Value.isAbsolute())
65 return false;
66
67 Res = evaluateAsInt64(Value.getConstant());
68 return true;
69 }
70
71 int64_t
evaluateAsInt64(int64_t Value) const72 PPCMCExpr::evaluateAsInt64(int64_t Value) const {
73 switch (Kind) {
74 case VK_PPC_LO:
75 return Value & 0xffff;
76 case VK_PPC_HI:
77 return (Value >> 16) & 0xffff;
78 case VK_PPC_HA:
79 return ((Value + 0x8000) >> 16) & 0xffff;
80 case VK_PPC_HIGH:
81 return (Value >> 16) & 0xffff;
82 case VK_PPC_HIGHA:
83 return ((Value + 0x8000) >> 16) & 0xffff;
84 case VK_PPC_HIGHER:
85 return (Value >> 32) & 0xffff;
86 case VK_PPC_HIGHERA:
87 return ((Value + 0x8000) >> 32) & 0xffff;
88 case VK_PPC_HIGHEST:
89 return (Value >> 48) & 0xffff;
90 case VK_PPC_HIGHESTA:
91 return ((Value + 0x8000) >> 48) & 0xffff;
92 case VK_PPC_None:
93 break;
94 }
95 llvm_unreachable("Invalid kind!");
96 }
97
98 bool
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const99 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
100 const MCAsmLayout *Layout,
101 const MCFixup *Fixup) const {
102 MCValue Value;
103
104 if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
105 return false;
106
107 if (Value.isAbsolute()) {
108 int64_t Result = evaluateAsInt64(Value.getConstant());
109 if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
110 (Result >= 0x8000))
111 return false;
112 Res = MCValue::get(Result);
113 } else {
114 if (!Layout)
115 return false;
116
117 MCContext &Context = Layout->getAssembler().getContext();
118 const MCSymbolRefExpr *Sym = Value.getSymA();
119 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
120 if (Modifier != MCSymbolRefExpr::VK_None)
121 return false;
122 switch (Kind) {
123 default:
124 llvm_unreachable("Invalid kind!");
125 case VK_PPC_LO:
126 Modifier = MCSymbolRefExpr::VK_PPC_LO;
127 break;
128 case VK_PPC_HI:
129 Modifier = MCSymbolRefExpr::VK_PPC_HI;
130 break;
131 case VK_PPC_HA:
132 Modifier = MCSymbolRefExpr::VK_PPC_HA;
133 break;
134 case VK_PPC_HIGH:
135 Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
136 break;
137 case VK_PPC_HIGHA:
138 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
139 break;
140 case VK_PPC_HIGHERA:
141 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
142 break;
143 case VK_PPC_HIGHER:
144 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
145 break;
146 case VK_PPC_HIGHEST:
147 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
148 break;
149 case VK_PPC_HIGHESTA:
150 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
151 break;
152 }
153 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
154 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
155 }
156
157 return true;
158 }
159
visitUsedExpr(MCStreamer & Streamer) const160 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
161 Streamer.visitUsedExpr(*getSubExpr());
162 }
163