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