1 //===-- PPCMCExpr.cpp - PPC specific MC expression classes ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PPCMCExpr.h" 10 #include "PPCFixupKinds.h" 11 #include "llvm/MC/MCAsmInfo.h" 12 #include "llvm/MC/MCAssembler.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCObjectStreamer.h" 15 16 using namespace llvm; 17 18 #define DEBUG_TYPE "ppcmcexpr" 19 20 const PPCMCExpr* 21 PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr, 22 bool IsDarwin, MCContext &Ctx) { 23 return new (Ctx) PPCMCExpr(Kind, Expr, IsDarwin); 24 } 25 26 void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 27 if (isDarwinSyntax()) { 28 switch (Kind) { 29 default: llvm_unreachable("Invalid kind!"); 30 case VK_PPC_LO: OS << "lo16"; break; 31 case VK_PPC_HI: OS << "hi16"; break; 32 case VK_PPC_HA: OS << "ha16"; break; 33 } 34 35 OS << '('; 36 getSubExpr()->print(OS, MAI); 37 OS << ')'; 38 } else { 39 getSubExpr()->print(OS, MAI); 40 41 switch (Kind) { 42 default: llvm_unreachable("Invalid kind!"); 43 case VK_PPC_LO: OS << "@l"; break; 44 case VK_PPC_HI: OS << "@h"; break; 45 case VK_PPC_HA: OS << "@ha"; break; 46 case VK_PPC_HIGH: OS << "@high"; break; 47 case VK_PPC_HIGHA: OS << "@higha"; break; 48 case VK_PPC_HIGHER: OS << "@higher"; break; 49 case VK_PPC_HIGHERA: OS << "@highera"; break; 50 case VK_PPC_HIGHEST: OS << "@highest"; break; 51 case VK_PPC_HIGHESTA: OS << "@highesta"; break; 52 } 53 } 54 } 55 56 bool 57 PPCMCExpr::evaluateAsConstant(int64_t &Res) const { 58 MCValue Value; 59 60 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) 61 return false; 62 63 if (!Value.isAbsolute()) 64 return false; 65 66 Res = evaluateAsInt64(Value.getConstant()); 67 return true; 68 } 69 70 int64_t 71 PPCMCExpr::evaluateAsInt64(int64_t Value) const { 72 switch (Kind) { 73 case VK_PPC_LO: 74 return Value & 0xffff; 75 case VK_PPC_HI: 76 return (Value >> 16) & 0xffff; 77 case VK_PPC_HA: 78 return ((Value + 0x8000) >> 16) & 0xffff; 79 case VK_PPC_HIGH: 80 return (Value >> 16) & 0xffff; 81 case VK_PPC_HIGHA: 82 return ((Value + 0x8000) >> 16) & 0xffff; 83 case VK_PPC_HIGHER: 84 return (Value >> 32) & 0xffff; 85 case VK_PPC_HIGHERA: 86 return ((Value + 0x8000) >> 32) & 0xffff; 87 case VK_PPC_HIGHEST: 88 return (Value >> 48) & 0xffff; 89 case VK_PPC_HIGHESTA: 90 return ((Value + 0x8000) >> 48) & 0xffff; 91 case VK_PPC_None: 92 break; 93 } 94 llvm_unreachable("Invalid kind!"); 95 } 96 97 bool 98 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 99 const MCAsmLayout *Layout, 100 const MCFixup *Fixup) const { 101 MCValue Value; 102 103 if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup)) 104 return false; 105 106 if (Value.isAbsolute()) { 107 int64_t Result = evaluateAsInt64(Value.getConstant()); 108 if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) && 109 (Result >= 0x8000)) 110 return false; 111 Res = MCValue::get(Result); 112 } else { 113 if (!Layout) 114 return false; 115 116 MCContext &Context = Layout->getAssembler().getContext(); 117 const MCSymbolRefExpr *Sym = Value.getSymA(); 118 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 119 if (Modifier != MCSymbolRefExpr::VK_None) 120 return false; 121 switch (Kind) { 122 default: 123 llvm_unreachable("Invalid kind!"); 124 case VK_PPC_LO: 125 Modifier = MCSymbolRefExpr::VK_PPC_LO; 126 break; 127 case VK_PPC_HI: 128 Modifier = MCSymbolRefExpr::VK_PPC_HI; 129 break; 130 case VK_PPC_HA: 131 Modifier = MCSymbolRefExpr::VK_PPC_HA; 132 break; 133 case VK_PPC_HIGH: 134 Modifier = MCSymbolRefExpr::VK_PPC_HIGH; 135 break; 136 case VK_PPC_HIGHA: 137 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; 138 break; 139 case VK_PPC_HIGHERA: 140 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; 141 break; 142 case VK_PPC_HIGHER: 143 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; 144 break; 145 case VK_PPC_HIGHEST: 146 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; 147 break; 148 case VK_PPC_HIGHESTA: 149 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; 150 break; 151 } 152 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 153 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 154 } 155 156 return true; 157 } 158 159 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 160 Streamer.visitUsedExpr(*getSubExpr()); 161 } 162