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