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/MCAsmInfo.h"
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCContext.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 (!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     if (!Layout)
90       return false;
91 
92     MCContext &Context = Layout->getAssembler().getContext();
93     const MCSymbolRefExpr *Sym = Value.getSymA();
94     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
95     if (Modifier != MCSymbolRefExpr::VK_None)
96       return false;
97     switch (Kind) {
98       default:
99         llvm_unreachable("Invalid kind!");
100       case VK_PPC_LO:
101         Modifier = MCSymbolRefExpr::VK_PPC_LO;
102         break;
103       case VK_PPC_HI:
104         Modifier = MCSymbolRefExpr::VK_PPC_HI;
105         break;
106       case VK_PPC_HA:
107         Modifier = MCSymbolRefExpr::VK_PPC_HA;
108         break;
109       case VK_PPC_HIGHERA:
110         Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA;
111         break;
112       case VK_PPC_HIGHER:
113         Modifier = MCSymbolRefExpr::VK_PPC_HIGHER;
114         break;
115       case VK_PPC_HIGHEST:
116         Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST;
117         break;
118       case VK_PPC_HIGHESTA:
119         Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA;
120         break;
121     }
122     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
123     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
124   }
125 
126   return true;
127 }
128 
129 // FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
130 // that method should be made public?
131 static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
132   switch (Value->getKind()) {
133   case MCExpr::Target:
134     llvm_unreachable("Can't handle nested target expr!");
135 
136   case MCExpr::Constant:
137     break;
138 
139   case MCExpr::Binary: {
140     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
141     AddValueSymbols_(BE->getLHS(), Asm);
142     AddValueSymbols_(BE->getRHS(), Asm);
143     break;
144   }
145 
146   case MCExpr::SymbolRef:
147     Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
148     break;
149 
150   case MCExpr::Unary:
151     AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
152     break;
153   }
154 }
155 
156 void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
157   AddValueSymbols_(getSubExpr(), Asm);
158 }
159