]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / PowerPC / MCTargetDesc / PPCMCExpr.cpp
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 "PPCMCExpr.h"
11 #include "PPCFixupKinds.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*
22 PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr,
23                   bool isDarwin, MCContext &Ctx) {
24   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
25 }
26
27 void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) 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, MAI);
38     OS << ')';
39   } else {
40     getSubExpr()->print(OS, MAI);
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_HIGH: OS << "@high"; break;
48     case VK_PPC_HIGHA: OS << "@higha"; break;
49     case VK_PPC_HIGHER: OS << "@higher"; break;
50     case VK_PPC_HIGHERA: OS << "@highera"; break;
51     case VK_PPC_HIGHEST: OS << "@highest"; break;
52     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
53     }
54   }
55 }
56
57 bool
58 PPCMCExpr::evaluateAsConstant(int64_t &Res) const {
59   MCValue Value;
60
61   if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr))
62     return false;
63
64   if (!Value.isAbsolute())
65     return false;
66
67   Res = evaluateAsInt64(Value.getConstant());
68   return true;
69 }
70
71 int64_t
72 PPCMCExpr::evaluateAsInt64(int64_t Value) const {
73   switch (Kind) {
74     case VK_PPC_LO:
75       return Value & 0xffff;
76     case VK_PPC_HI:
77       return (Value >> 16) & 0xffff;
78     case VK_PPC_HA:
79       return ((Value + 0x8000) >> 16) & 0xffff;
80     case VK_PPC_HIGH:
81       return (Value >> 16) & 0xffff;
82     case VK_PPC_HIGHA:
83       return ((Value + 0x8000) >> 16) & 0xffff;
84     case VK_PPC_HIGHER:
85       return (Value >> 32) & 0xffff;
86     case VK_PPC_HIGHERA:
87       return ((Value + 0x8000) >> 32) & 0xffff;
88     case VK_PPC_HIGHEST:
89       return (Value >> 48) & 0xffff;
90     case VK_PPC_HIGHESTA:
91       return ((Value + 0x8000) >> 48) & 0xffff;
92     case VK_PPC_None:
93       break;
94   }
95   llvm_unreachable("Invalid kind!");
96 }
97
98 bool
99 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
100                                      const MCAsmLayout *Layout,
101                                      const MCFixup *Fixup) const {
102   MCValue Value;
103
104   if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup))
105     return false;
106
107   if (Value.isAbsolute()) {
108     int64_t Result = evaluateAsInt64(Value.getConstant());
109     if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
110         (Result >= 0x8000))
111       return false;
112     Res = MCValue::get(Result);
113   } else {
114     if (!Layout)
115       return false;
116
117     MCContext &Context = Layout->getAssembler().getContext();
118     const MCSymbolRefExpr *Sym = Value.getSymA();
119     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
120     if (Modifier != MCSymbolRefExpr::VK_None)
121       return false;
122     switch (Kind) {
123       default:
124         llvm_unreachable("Invalid kind!");
125       case VK_PPC_LO:
126         Modifier = MCSymbolRefExpr::VK_PPC_LO;
127         break;
128       case VK_PPC_HI:
129         Modifier = MCSymbolRefExpr::VK_PPC_HI;
130         break;
131       case VK_PPC_HA:
132         Modifier = MCSymbolRefExpr::VK_PPC_HA;
133         break;
134       case VK_PPC_HIGH:
135         Modifier = MCSymbolRefExpr::VK_PPC_HIGH;
136         break;
137       case VK_PPC_HIGHA:
138         Modifier = MCSymbolRefExpr::VK_PPC_HIGHA;
139         break;
140       case VK_PPC_HIGHERA:
141         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
142         break;
143       case VK_PPC_HIGHER:
144         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
145         break;
146       case VK_PPC_HIGHEST:
147         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
148         break;
149       case VK_PPC_HIGHESTA:
150         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
151         break;
152     }
153     Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context);
154     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
155   }
156
157   return true;
158 }
159
160 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
161   Streamer.visitUsedExpr(*getSubExpr());
162 }