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 15 using namespace llvm; 16 17 const PPCMCExpr* 18 PPCMCExpr::Create(VariantKind Kind, const MCExpr *Expr, 19 MCContext &Ctx) { 20 return new (Ctx) PPCMCExpr(Kind, Expr); 21 } 22 23 void 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 35 bool 36 PPCMCExpr::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? 81 static 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 106 void PPCMCExpr::AddValueSymbols(MCAssembler *Asm) const { 107 AddValueSymbols_(getSubExpr(), Asm); 108 } 109