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
16using namespace llvm;
17
18#define DEBUG_TYPE "ppcmcexpr"
19
20const PPCMCExpr *PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
21 MCContext &Ctx) {
22 return new (Ctx) PPCMCExpr(Kind, Expr);
23}
24
25void 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
61bool
62PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
63 MCValue Value;
64
65 if (!getSubExpr()->evaluateAsRelocatable(Res&: Value, Asm: nullptr, Fixup: nullptr))
66 return false;
67
68 if (!Value.isAbsolute())
69 return false;
70
71 Res = evaluateAsInt64(Value: Value.getConstant());
72 return true;
73}
74
75int64_t
76PPCMCExpr::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
102bool PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
103 const MCFixup *Fixup) const {
104 MCValue Value;
105
106 if (!getSubExpr()->evaluateAsRelocatable(Res&: Value, Asm, Fixup))
107 return false;
108
109 if (Value.isAbsolute()) {
110 int64_t Result = evaluateAsInt64(Value: Value.getConstant());
111 bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16;
112 bool IsHalf16DS =
113 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds;
114 bool IsHalf16DQ =
115 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq;
116 bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ;
117
118 if (!IsHalf && Result >= 0x8000)
119 return false;
120 if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf)))
121 return false;
122
123 Res = MCValue::get(Val: Result);
124 } else {
125 if (!Asm || !Asm->hasLayout())
126 return false;
127
128 MCContext &Context = Asm->getContext();
129 const MCSymbolRefExpr *Sym = Value.getSymA();
130 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
131 if (Modifier != MCSymbolRefExpr::VK_None)
132 return false;
133 switch (Kind) {
134 default:
135 llvm_unreachable("Invalid kind!");
136 case VK_PPC_LO:
137 Modifier = MCSymbolRefExpr::VK_PPC_LO;
138 break;
139 case VK_PPC_HI:
140 Modifier = MCSymbolRefExpr::VK_PPC_HI;
141 break;
142 case VK_PPC_HA:
143 Modifier = MCSymbolRefExpr::VK_PPC_HA;
144 break;
145 case VK_PPC_HIGH:
146 Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
147 break;
148 case VK_PPC_HIGHA:
149 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
150 break;
151 case VK_PPC_HIGHERA:
152 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
153 break;
154 case VK_PPC_HIGHER:
155 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
156 break;
157 case VK_PPC_HIGHEST:
158 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
159 break;
160 case VK_PPC_HIGHESTA:
161 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
162 break;
163 }
164 Sym = MCSymbolRefExpr::create(Symbol: &Sym->getSymbol(), Kind: Modifier, Ctx&: Context);
165 Res = MCValue::get(SymA: Sym, SymB: Value.getSymB(), Val: Value.getConstant());
166 }
167
168 return true;
169}
170
171void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
172 Streamer.visitUsedExpr(Expr: *getSubExpr());
173}
174