blob: f0613ff63289a2e4b05b29d2ecfc9a5ceacf8d7e [file] [log] [blame]
Ulrich Weigand41789de2013-05-23 22:26:41 +00001//===-- 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
15using namespace llvm;
16
17const PPCMCExpr*
18PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
19 MCContext &Ctx) {
20 return new (Ctx) PPCMCExpr(Kind, Expr);
21}
22
23void PPCMCExpr::PrintImpl(raw_ostream &OS) const {
24 switch (Kind) {
25 default: llvm_unreachable("Invalid kind!");
26 case VK_PPC_HA16: OS << "ha16"; break;
27 case VK_PPC_LO16: OS << "lo16"; break;
28 }
29
30 OS << '(';
31 getSubExpr()->print(OS);
32 OS << ')';
33}
34
35bool
36PPCMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
37 const MCAsmLayout *Layout) const {
38 MCValue Value;
39
40 if (!getSubExpr()->EvaluateAsRelocatable(Value, *Layout))
41 return false;
42
43 if (Value.isAbsolute()) {
44 int64_t Result = Value.getConstant();
45 switch (Kind) {
46 default:
47 llvm_unreachable("Invalid kind!");
48 case VK_PPC_HA16:
49 Result = ((Result >> 16) + ((Result & 0x8000) ? 1 : 0)) & 0xffff;
50 break;
51 case VK_PPC_LO16:
52 Result = Result & 0xffff;
53 break;
54 }
55 Res = MCValue::get(Result);
56 } else {
57 MCContext &Context = Layout->getAssembler().getContext();
58 const MCSymbolRefExpr *Sym = Value.getSymA();
59 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind();
60 if (Modifier != MCSymbolRefExpr::VK_None)
61 return false;
62 switch (Kind) {
63 default:
64 llvm_unreachable("Invalid kind!");
65 case VK_PPC_HA16:
66 Modifier = MCSymbolRefExpr::VK_PPC_ADDR16_HA;
67 break;
68 case VK_PPC_LO16:
69 Modifier = MCSymbolRefExpr::VK_PPC_ADDR16_LO;
70 break;
71 }
72 Sym = MCSymbolRefExpr::Create(&Sym->getSymbol(), Modifier, Context);
73 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant());
74 }
75
76 return true;
77}
78
79// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
80// that method should be made public?
81static void AddValueSymbols_(const MCExpr *Value, MCAssembler *Asm) {
82 switch (Value->getKind()) {
83 case MCExpr::Target:
84 llvm_unreachable("Can't handle nested target expr!");
85
86 case MCExpr::Constant:
87 break;
88
89 case MCExpr::Binary: {
90 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
91 AddValueSymbols_(BE->getLHS(), Asm);
92 AddValueSymbols_(BE->getRHS(), Asm);
93 break;
94 }
95
96 case MCExpr::SymbolRef:
97 Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
98 break;
99
100 case MCExpr::Unary:
101 AddValueSymbols_(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
102 break;
103 }
104}
105
106void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const {
107 AddValueSymbols_(getSubExpr(), Asm);
108}