xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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 *PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
21                                    MCContext &Ctx) {
22   return new (Ctx) PPCMCExpr(Kind, Expr);
23 }
24 
25 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
62 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
76 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
103 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 
164 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
165   Streamer.visitUsedExpr(*getSubExpr());
166 }
167