1 //===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "PPCMCExpr.h"
10 #include "PPCFixupKinds.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
create(VariantKind Kind,const MCExpr * Expr,MCContext & Ctx)20 const PPCMCExpr *PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
21 MCContext &Ctx) {
22 return new (Ctx) PPCMCExpr(Kind, Expr);
23 }
24
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const25 void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
26 getSubExpr()->print(OS, MAI);
27
28 switch (Kind) {
29 default:
30 llvm_unreachable("Invalid kind!");
31 case VK_PPC_LO:
32 OS << "@l";
33 break;
34 case VK_PPC_HI:
35 OS << "@h";
36 break;
37 case VK_PPC_HA:
38 OS << "@ha";
39 break;
40 case VK_PPC_HIGH:
41 OS << "@high";
42 break;
43 case VK_PPC_HIGHA:
44 OS << "@higha";
45 break;
46 case VK_PPC_HIGHER:
47 OS << "@higher";
48 break;
49 case VK_PPC_HIGHERA:
50 OS << "@highera";
51 break;
52 case VK_PPC_HIGHEST:
53 OS << "@highest";
54 break;
55 case VK_PPC_HIGHESTA:
56 OS << "@highesta";
57 break;
58 }
59 }
60
61 bool
evaluateAsConstant(int64_t & Res) const62 PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
63 MCValue Value;
64
65 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
66 return false;
67
68 if (!Value.isAbsolute())
69 return false;
70
71 Res = evaluateAsInt64(Value.getConstant());
72 return true;
73 }
74
75 int64_t
evaluateAsInt64(int64_t Value) const76 PPCMCExpr::evaluateAsInt64(int64_t Value) const {
77 switch (Kind) {
78 case VK_PPC_LO:
79 return Value & 0xffff;
80 case VK_PPC_HI:
81 return (Value >> 16) & 0xffff;
82 case VK_PPC_HA:
83 return ((Value + 0x8000) >> 16) & 0xffff;
84 case VK_PPC_HIGH:
85 return (Value >> 16) & 0xffff;
86 case VK_PPC_HIGHA:
87 return ((Value + 0x8000) >> 16) & 0xffff;
88 case VK_PPC_HIGHER:
89 return (Value >> 32) & 0xffff;
90 case VK_PPC_HIGHERA:
91 return ((Value + 0x8000) >> 32) & 0xffff;
92 case VK_PPC_HIGHEST:
93 return (Value >> 48) & 0xffff;
94 case VK_PPC_HIGHESTA:
95 return ((Value + 0x8000) >> 48) & 0xffff;
96 case VK_PPC_None:
97 break;
98 }
99 llvm_unreachable("Invalid kind!");
100 }
101
102 bool
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const103 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
104 const MCAsmLayout *Layout,
105 const MCFixup *Fixup) const {
106 MCValue Value;
107
108 if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
109 return false;
110
111 if (Value.isAbsolute()) {
112 int64_t Result = evaluateAsInt64(Value.getConstant());
113 if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
114 (Result >= 0x8000))
115 return false;
116 Res = MCValue::get(Result);
117 } else {
118 if (!Layout)
119 return false;
120
121 MCContext &Context = Layout->getAssembler().getContext();
122 const MCSymbolRefExpr *Sym = Value.getSymA();
123 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
124 if (Modifier != MCSymbolRefExpr::VK_None)
125 return false;
126 switch (Kind) {
127 default:
128 llvm_unreachable("Invalid kind!");
129 case VK_PPC_LO:
130 Modifier = MCSymbolRefExpr::VK_PPC_LO;
131 break;
132 case VK_PPC_HI:
133 Modifier = MCSymbolRefExpr::VK_PPC_HI;
134 break;
135 case VK_PPC_HA:
136 Modifier = MCSymbolRefExpr::VK_PPC_HA;
137 break;
138 case VK_PPC_HIGH:
139 Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
140 break;
141 case VK_PPC_HIGHA:
142 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
143 break;
144 case VK_PPC_HIGHERA:
145 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
146 break;
147 case VK_PPC_HIGHER:
148 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
149 break;
150 case VK_PPC_HIGHEST:
151 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
152 break;
153 case VK_PPC_HIGHESTA:
154 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
155 break;
156 }
157 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
158 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
159 }
160
161 return true;
162 }
163
visitUsedExpr(MCStreamer & Streamer) const164 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
165 Streamer.visitUsedExpr(*getSubExpr());
166 }
167