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 *PPCMCExpr::create(VariantKind Kind, const MCExpr *Expr, 21 MCContext &Ctx) { 22 return new (Ctx) PPCMCExpr(Kind, Expr); 23 } 24 25 void PPCMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { 26 getSubExpr()->print(OS, MAI); 27 28 switch (Kind) { 29 default: 30 llvm_unreachable("Invalid kind!"); 31 case VK_PPC_LO: 32 OS << "@l"; 33 break; 34 case VK_PPC_HI: 35 OS << "@h"; 36 break; 37 case VK_PPC_HA: 38 OS << "@ha"; 39 break; 40 case VK_PPC_HIGH: 41 OS << "@high"; 42 break; 43 case VK_PPC_HIGHA: 44 OS << "@higha"; 45 break; 46 case VK_PPC_HIGHER: 47 OS << "@higher"; 48 break; 49 case VK_PPC_HIGHERA: 50 OS << "@highera"; 51 break; 52 case VK_PPC_HIGHEST: 53 OS << "@highest"; 54 break; 55 case VK_PPC_HIGHESTA: 56 OS << "@highesta"; 57 break; 58 } 59 } 60 61 bool 62 PPCMCExpr::evaluateAsConstant(int64_t &Res) const { 63 MCValue Value; 64 65 if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) 66 return false; 67 68 if (!Value.isAbsolute()) 69 return false; 70 71 Res = evaluateAsInt64(Value.getConstant()); 72 return true; 73 } 74 75 int64_t 76 PPCMCExpr::evaluateAsInt64(int64_t Value) const { 77 switch (Kind) { 78 case VK_PPC_LO: 79 return Value & 0xffff; 80 case VK_PPC_HI: 81 return (Value >> 16) & 0xffff; 82 case VK_PPC_HA: 83 return ((Value + 0x8000) >> 16) & 0xffff; 84 case VK_PPC_HIGH: 85 return (Value >> 16) & 0xffff; 86 case VK_PPC_HIGHA: 87 return ((Value + 0x8000) >> 16) & 0xffff; 88 case VK_PPC_HIGHER: 89 return (Value >> 32) & 0xffff; 90 case VK_PPC_HIGHERA: 91 return ((Value + 0x8000) >> 32) & 0xffff; 92 case VK_PPC_HIGHEST: 93 return (Value >> 48) & 0xffff; 94 case VK_PPC_HIGHESTA: 95 return ((Value + 0x8000) >> 48) & 0xffff; 96 case VK_PPC_None: 97 break; 98 } 99 llvm_unreachable("Invalid kind!"); 100 } 101 102 bool 103 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, 104 const MCAsmLayout *Layout, 105 const MCFixup *Fixup) const { 106 MCValue Value; 107 108 if (!getSubExpr()->evaluateAsRelocatable(Value, Layout, Fixup)) 109 return false; 110 111 if (Value.isAbsolute()) { 112 int64_t Result = evaluateAsInt64(Value.getConstant()); 113 bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16; 114 bool IsHalf16DS = 115 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds; 116 bool IsHalf16DQ = 117 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq; 118 bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ; 119 120 if (!IsHalf && Result >= 0x8000) 121 return false; 122 if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf))) 123 return false; 124 125 Res = MCValue::get(Result); 126 } else { 127 if (!Layout) 128 return false; 129 130 MCContext &Context = Layout->getAssembler().getContext(); 131 const MCSymbolRefExpr *Sym = Value.getSymA(); 132 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 133 if (Modifier != MCSymbolRefExpr::VK_None) 134 return false; 135 switch (Kind) { 136 default: 137 llvm_unreachable("Invalid kind!"); 138 case VK_PPC_LO: 139 Modifier = MCSymbolRefExpr::VK_PPC_LO; 140 break; 141 case VK_PPC_HI: 142 Modifier = MCSymbolRefExpr::VK_PPC_HI; 143 break; 144 case VK_PPC_HA: 145 Modifier = MCSymbolRefExpr::VK_PPC_HA; 146 break; 147 case VK_PPC_HIGH: 148 Modifier = MCSymbolRefExpr::VK_PPC_HIGH; 149 break; 150 case VK_PPC_HIGHA: 151 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; 152 break; 153 case VK_PPC_HIGHERA: 154 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; 155 break; 156 case VK_PPC_HIGHER: 157 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; 158 break; 159 case VK_PPC_HIGHEST: 160 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; 161 break; 162 case VK_PPC_HIGHESTA: 163 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; 164 break; 165 } 166 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 167 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 168 } 169 170 return true; 171 } 172 173 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 174 Streamer.visitUsedExpr(*getSubExpr()); 175 } 176