xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
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*
21 PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
22                   bool IsDarwin, MCContext &Ctx) {
23   return new (Ctx) PPCMCExpr(Kind, Expr, IsDarwin);
24 }
25 
26 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
57 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
71 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
98 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 
159 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
160   Streamer.visitUsedExpr(*getSubExpr());
161 }
162