xref: /aosp_15_r20/external/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "PPCFixupKinds.h"
11*9880d681SAndroid Build Coastguard Worker #include "PPCMCExpr.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectStreamer.h"
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker using namespace llvm;
18*9880d681SAndroid Build Coastguard Worker 
19*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "ppcmcexpr"
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker const PPCMCExpr*
create(VariantKind Kind,const MCExpr * Expr,bool isDarwin,MCContext & Ctx)22*9880d681SAndroid Build Coastguard Worker PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
23*9880d681SAndroid Build Coastguard Worker                   bool isDarwin, MCContext &Ctx) {
24*9880d681SAndroid Build Coastguard Worker   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
25*9880d681SAndroid Build Coastguard Worker }
26*9880d681SAndroid Build Coastguard Worker 
printImpl(raw_ostream & OS,const MCAsmInfo * MAI) const27*9880d681SAndroid Build Coastguard Worker void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
28*9880d681SAndroid Build Coastguard Worker   if (isDarwinSyntax()) {
29*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
30*9880d681SAndroid Build Coastguard Worker     default: llvm_unreachable("Invalid kind!");
31*9880d681SAndroid Build Coastguard Worker     case VK_PPC_LO: OS << "lo16"; break;
32*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HI: OS << "hi16"; break;
33*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HA: OS << "ha16"; break;
34*9880d681SAndroid Build Coastguard Worker     }
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker     OS << '(';
37*9880d681SAndroid Build Coastguard Worker     getSubExpr()->print(OS, MAI);
38*9880d681SAndroid Build Coastguard Worker     OS << ')';
39*9880d681SAndroid Build Coastguard Worker   } else {
40*9880d681SAndroid Build Coastguard Worker     getSubExpr()->print(OS, MAI);
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
43*9880d681SAndroid Build Coastguard Worker     default: llvm_unreachable("Invalid kind!");
44*9880d681SAndroid Build Coastguard Worker     case VK_PPC_LO: OS << "@l"; break;
45*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HI: OS << "@h"; break;
46*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HA: OS << "@ha"; break;
47*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHER: OS << "@higher"; break;
48*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHERA: OS << "@highera"; break;
49*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHEST: OS << "@highest"; break;
50*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
51*9880d681SAndroid Build Coastguard Worker     }
52*9880d681SAndroid Build Coastguard Worker   }
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker bool
evaluateAsConstant(int64_t & Res) const56*9880d681SAndroid Build Coastguard Worker PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
57*9880d681SAndroid Build Coastguard Worker   MCValue Value;
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
60*9880d681SAndroid Build Coastguard Worker     return false;
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   if (!Value.isAbsolute())
63*9880d681SAndroid Build Coastguard Worker     return false;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   Res = evaluateAsInt64(Value.getConstant());
66*9880d681SAndroid Build Coastguard Worker   return true;
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker int64_t
evaluateAsInt64(int64_t Value) const70*9880d681SAndroid Build Coastguard Worker PPCMCExpr::evaluateAsInt64(int64_t Value) const {
71*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
72*9880d681SAndroid Build Coastguard Worker     case VK_PPC_LO:
73*9880d681SAndroid Build Coastguard Worker       return Value & 0xffff;
74*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HI:
75*9880d681SAndroid Build Coastguard Worker       return (Value >> 16) & 0xffff;
76*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HA:
77*9880d681SAndroid Build Coastguard Worker       return ((Value + 0x8000) >> 16) & 0xffff;
78*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHER:
79*9880d681SAndroid Build Coastguard Worker       return (Value >> 32) & 0xffff;
80*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHERA:
81*9880d681SAndroid Build Coastguard Worker       return ((Value + 0x8000) >> 32) & 0xffff;
82*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHEST:
83*9880d681SAndroid Build Coastguard Worker       return (Value >> 48) & 0xffff;
84*9880d681SAndroid Build Coastguard Worker     case VK_PPC_HIGHESTA:
85*9880d681SAndroid Build Coastguard Worker       return ((Value + 0x8000) >> 48) & 0xffff;
86*9880d681SAndroid Build Coastguard Worker     case VK_PPC_None:
87*9880d681SAndroid Build Coastguard Worker       break;
88*9880d681SAndroid Build Coastguard Worker   }
89*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Invalid kind!");
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker 
92*9880d681SAndroid Build Coastguard Worker bool
evaluateAsRelocatableImpl(MCValue & Res,const MCAsmLayout * Layout,const MCFixup * Fixup) const93*9880d681SAndroid Build Coastguard Worker PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
94*9880d681SAndroid Build Coastguard Worker                                      const MCAsmLayout *Layout,
95*9880d681SAndroid Build Coastguard Worker                                      const MCFixup *Fixup) const {
96*9880d681SAndroid Build Coastguard Worker   MCValue Value;
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker   if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
99*9880d681SAndroid Build Coastguard Worker     return false;
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   if (Value.isAbsolute()) {
102*9880d681SAndroid Build Coastguard Worker     int64_t Result = evaluateAsInt64(Value.getConstant());
103*9880d681SAndroid Build Coastguard Worker     if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
104*9880d681SAndroid Build Coastguard Worker         (Result >= 0x8000))
105*9880d681SAndroid Build Coastguard Worker       return false;
106*9880d681SAndroid Build Coastguard Worker     Res = MCValue::get(Result);
107*9880d681SAndroid Build Coastguard Worker   } else {
108*9880d681SAndroid Build Coastguard Worker     if (!Layout)
109*9880d681SAndroid Build Coastguard Worker       return false;
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker     MCContext &Context = Layout->getAssembler().getContext();
112*9880d681SAndroid Build Coastguard Worker     const MCSymbolRefExpr *Sym = Value.getSymA();
113*9880d681SAndroid Build Coastguard Worker     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
114*9880d681SAndroid Build Coastguard Worker     if (Modifier != MCSymbolRefExpr::VK_None)
115*9880d681SAndroid Build Coastguard Worker       return false;
116*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
117*9880d681SAndroid Build Coastguard Worker       default:
118*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("Invalid kind!");
119*9880d681SAndroid Build Coastguard Worker       case VK_PPC_LO:
120*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_LO;
121*9880d681SAndroid Build Coastguard Worker         break;
122*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HI:
123*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HI;
124*9880d681SAndroid Build Coastguard Worker         break;
125*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HA:
126*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HA;
127*9880d681SAndroid Build Coastguard Worker         break;
128*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HIGHERA:
129*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
130*9880d681SAndroid Build Coastguard Worker         break;
131*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HIGHER:
132*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
133*9880d681SAndroid Build Coastguard Worker         break;
134*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HIGHEST:
135*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
136*9880d681SAndroid Build Coastguard Worker         break;
137*9880d681SAndroid Build Coastguard Worker       case VK_PPC_HIGHESTA:
138*9880d681SAndroid Build Coastguard Worker         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
139*9880d681SAndroid Build Coastguard Worker         break;
140*9880d681SAndroid Build Coastguard Worker     }
141*9880d681SAndroid Build Coastguard Worker     Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
142*9880d681SAndroid Build Coastguard Worker     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
143*9880d681SAndroid Build Coastguard Worker   }
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   return true;
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker 
visitUsedExpr(MCStreamer & Streamer) const148*9880d681SAndroid Build Coastguard Worker void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
149*9880d681SAndroid Build Coastguard Worker   Streamer.visitUsedExpr(*getSubExpr());
150*9880d681SAndroid Build Coastguard Worker }
151