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 bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16;
114 bool IsHalf16DS =
115 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds;
116 bool IsHalf16DQ =
117 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq;
118 bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ;
119
120 if (!IsHalf && Result >= 0x8000)
121 return false;
122 if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf)))
123 return false;
124
125 Res = MCValue::get(Result);
126 } else {
127 if (!Layout)
128 return false;
129
130 MCContext &Context = Layout->getAssembler().getContext();
131 const MCSymbolRefExpr *Sym = Value.getSymA();
132 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
133 if (Modifier != MCSymbolRefExpr::VK_None)
134 return false;
135 switch (Kind) {
136 default:
137 llvm_unreachable("Invalid kind!");
138 case VK_PPC_LO:
139 Modifier = MCSymbolRefExpr::VK_PPC_LO;
140 break;
141 case VK_PPC_HI:
142 Modifier = MCSymbolRefExpr::VK_PPC_HI;
143 break;
144 case VK_PPC_HA:
145 Modifier = MCSymbolRefExpr::VK_PPC_HA;
146 break;
147 case VK_PPC_HIGH:
148 Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
149 break;
150 case VK_PPC_HIGHA:
151 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
152 break;
153 case VK_PPC_HIGHERA:
154 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
155 break;
156 case VK_PPC_HIGHER:
157 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
158 break;
159 case VK_PPC_HIGHEST:
160 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
161 break;
162 case VK_PPC_HIGHESTA:
163 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
164 break;
165 }
166 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
167 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
168 }
169
170 return true;
171 }
172
visitUsedExpr(MCStreamer & Streamer) const173 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
174 Streamer.visitUsedExpr(*getSubExpr());
175 }
176