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                        MCContext &Ctx) {
21   int AssemblerDialect = Ctx.getAsmInfo()->getAssemblerDialect();
22   return new (Ctx) PPCMCExpr(Kind, Expr, AssemblerDialect);
23 }
24 
25 void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
26   if (isDarwinSyntax()) {
27     switch (Kind) {
28     default: llvm_unreachable("Invalid kind!");
29     case VK_PPC_LO: OS << "lo16"; break;
30     case VK_PPC_HI: OS << "hi16"; break;
31     case VK_PPC_HA: OS << "ha16"; break;
32     }
33 
34     OS << '(';
35     getSubExpr()->print(OS);
36     OS << ')';
37   } else {
38     getSubExpr()->print(OS);
39 
40     switch (Kind) {
41     default: llvm_unreachable("Invalid kind!");
42     case VK_PPC_LO: OS << "@l"; break;
43     case VK_PPC_HI: OS << "@h"; break;
44     case VK_PPC_HA: OS << "@ha"; break;
45     }
46   }
47 }
48 
49 bool
50 PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
51                                      const MCAsmLayout *Layout) const {
52   MCValue Value;
53 
54   if (!getSubExpr()->EvaluateAsRelocatable(Value, *Layout))
55     return false;
56 
57   if (Value.isAbsolute()) {
58     int64_t Result = Value.getConstant();
59     switch (Kind) {
60       default:
61         llvm_unreachable("Invalid kind!");
62       case VK_PPC_LO:
63         Result = Result & 0xffff;
64         break;
65       case VK_PPC_HI:
66         Result = (Result >> 16) & 0xffff;
67         break;
68       case VK_PPC_HA:
69         Result = ((Result >> 16) + ((Result & 0x8000) ? 1 : 0)) & 0xffff;
70         break;
71     }
72     Res = MCValue::get(Result);
73   } else {
74     MCContext &Context = Layout->getAssembler().getContext();
75     const MCSymbolRefExpr *Sym = Value.getSymA();
76     MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
77     if (Modifier != MCSymbolRefExpr::VK_None)
78       return false;
79     switch (Kind) {
80       default:
81         llvm_unreachable("Invalid kind!");
82       case VK_PPC_LO:
83         Modifier = MCSymbolRefExpr::VK_PPC_LO;
84         break;
85       case VK_PPC_HI:
86         Modifier = MCSymbolRefExpr::VK_PPC_HI;
87         break;
88       case VK_PPC_HA:
89         Modifier = MCSymbolRefExpr::VK_PPC_HA;
90         break;
91     }
92     Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
93     Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
94   }
95 
96   return true;
97 }
98 
99 // FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
100 // that method should be made public?
101 static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
102   switch (Value->getKind()) {
103   case MCExpr::Target:
104     llvm_unreachable("Can't handle nested target expr!");
105 
106   case MCExpr::Constant:
107     break;
108 
109   case MCExpr::Binary: {
110     const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
111     AddValueSymbols_(BE->getLHS(), Asm);
112     AddValueSymbols_(BE->getRHS(), Asm);
113     break;
114   }
115 
116   case MCExpr::SymbolRef:
117     Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
118     break;
119 
120   case MCExpr::Unary:
121     AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
122     break;
123   }
124 }
125 
126 void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
127   AddValueSymbols_(getSubExpr(), Asm);
128 }
129