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