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 PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 103 const MCFixup *Fixup) const { 104 MCValue Value; 105 106 if (!getSubExpr()->evaluateAsRelocatable(Value, Asm, Fixup)) 107 return false; 108 109 if (Value.isAbsolute()) { 110 int64_t Result = evaluateAsInt64(Value.getConstant()); 111 bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16; 112 bool IsHalf16DS = 113 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds; 114 bool IsHalf16DQ = 115 Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq; 116 bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ; 117 118 if (!IsHalf && Result >= 0x8000) 119 return false; 120 if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf))) 121 return false; 122 123 Res = MCValue::get(Result); 124 } else { 125 if (!Asm || !Asm->hasLayout()) 126 return false; 127 128 MCContext &Context = Asm->getContext(); 129 const MCSymbolRefExpr *Sym = Value.getSymA(); 130 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 131 if (Modifier != MCSymbolRefExpr::VK_None) 132 return false; 133 switch (Kind) { 134 default: 135 llvm_unreachable("Invalid kind!"); 136 case VK_PPC_LO: 137 Modifier = MCSymbolRefExpr::VK_PPC_LO; 138 break; 139 case VK_PPC_HI: 140 Modifier = MCSymbolRefExpr::VK_PPC_HI; 141 break; 142 case VK_PPC_HA: 143 Modifier = MCSymbolRefExpr::VK_PPC_HA; 144 break; 145 case VK_PPC_HIGH: 146 Modifier = MCSymbolRefExpr::VK_PPC_HIGH; 147 break; 148 case VK_PPC_HIGHA: 149 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; 150 break; 151 case VK_PPC_HIGHERA: 152 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; 153 break; 154 case VK_PPC_HIGHER: 155 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; 156 break; 157 case VK_PPC_HIGHEST: 158 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; 159 break; 160 case VK_PPC_HIGHESTA: 161 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; 162 break; 163 } 164 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 165 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 166 } 167 168 return true; 169 } 170 171 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 172 Streamer.visitUsedExpr(*getSubExpr()); 173 } 174