]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 #define DEBUG_TYPE "ppcmcexpr"
11 #include "PPCMCExpr.h"
12 #include "llvm/MC/MCAssembler.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCAsmInfo.h"
15
16 using namespace llvm;
17
18 const PPCMCExpr*
19 PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
20                   bool isDarwin, MCContext &Ctx) {
21   return new (Ctx) PPCMCExpr(Kind, Expr, isDarwin);
22 }
23
24 void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
25   if (isDarwinSyntax()) {
26     switch (Kind) {
27     default: llvm_unreachable("Invalid kind!");
28     case VK_PPC_LO: OS << "lo16"; break;
29     case VK_PPC_HI: OS << "hi16"; break;
30     case VK_PPC_HA: OS << "ha16"; break;
31     }
32
33     OS << '(';
34     getSubExpr()->print(OS);
35     OS << ')';
36   } else {
37     getSubExpr()->print(OS);
38
39     switch (Kind) {
40     default: llvm_unreachable("Invalid kind!");
41     case VK_PPC_LO: OS << "@l"; break;
42     case VK_PPC_HI: OS << "@h"; break;
43     case VK_PPC_HA: OS << "@ha"; break;
44     case VK_PPC_HIGHER: OS << "@higher"; break;
45     case VK_PPC_HIGHERA: OS << "@highera"; break;
46     case VK_PPC_HIGHEST: OS << "@highest"; break;
47     case VK_PPC_HIGHESTA: OS << "@highesta"; break;
48     }
49   }
50 }
51
52 bool
53 PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
54                                      const MCAsmLayout *Layout) const {
55   MCValue Value;
56
57   if (!Layout || !getSubExpr()->EvaluateAsRelocatable(Value, *Layout))
58     return false;
59
60   if (Value.isAbsolute()) {
61     int64_t Result = Value.getConstant();
62     switch (Kind) {
63       default:
64         llvm_unreachable("Invalid kind!");
65       case VK_PPC_LO:
66         Result = Result & 0xffff;
67         break;
68       case VK_PPC_HI:
69         Result = (Result >> 16) & 0xffff;
70         break;
71       case VK_PPC_HA:
72         Result = ((Result + 0x8000) >> 16) & 0xffff;
73         break;
74       case VK_PPC_HIGHER:
75         Result = (Result >> 32) & 0xffff;
76         break;
77       case VK_PPC_HIGHERA:
78         Result = ((Result + 0x8000) >> 32) & 0xffff;
79         break;
80       case VK_PPC_HIGHEST:
81         Result = (Result >> 48) & 0xffff;
82         break;
83       case VK_PPC_HIGHESTA:
84         Result = ((Result + 0x8000) >> 48) & 0xffff;
85         break;
86     }
87     Res = MCValue::get(Result);
88   } else {
89     MCContext &Context = Layout->getAssembler().getContext();
90     const MCSymbolRefExpr *Sym = Value.getSymA();
91     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
92     if (Modifier != MCSymbolRefExpr::VK_None)
93       return false;
94     switch (Kind) {
95       default:
96         llvm_unreachable("Invalid kind!");
97       case VK_PPC_LO:
98         Modifier = MCSymbolRefExpr::VK_PPC_LO;
99         break;
100       case VK_PPC_HI:
101         Modifier = MCSymbolRefExpr::VK_PPC_HI;
102         break;
103       case VK_PPC_HA:
104         Modifier = MCSymbolRefExpr::VK_PPC_HA;
105         break;
106       case VK_PPC_HIGHERA:
107         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
108         break;
109       case VK_PPC_HIGHER:
110         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
111         break;
112       case VK_PPC_HIGHEST:
113         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
114         break;
115       case VK_PPC_HIGHESTA:
116         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
117         break;
118     }
119     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
120     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
121   }
122
123   return true;
124 }
125
126 // FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
127 // that method should be made public?
128 static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
129   switch (Value->getKind()) {
130   case MCExpr::Target:
131     llvm_unreachable("Can't handle nested target expr!");
132
133   case MCExpr::Constant:
134     break;
135
136   case MCExpr::Binary: {
137     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
138     AddValueSymbols_(BE->getLHS(), Asm);
139     AddValueSymbols_(BE->getRHS(), Asm);
140     break;
141   }
142
143   case MCExpr::SymbolRef:
144     Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
145     break;
146
147   case MCExpr::Unary:
148     AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
149     break;
150   }
151 }
152
153 void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
154   AddValueSymbols_(getSubExpr(), Asm);
155 }