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 if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) && 114 (Result >= 0x8000)) 115 return false; 116 Res = MCValue::get(Result); 117 } else { 118 if (!Layout) 119 return false; 120 121 MCContext &Context = Layout->getAssembler().getContext(); 122 const MCSymbolRefExpr *Sym = Value.getSymA(); 123 MCSymbolRefExpr::VariantKind Modifier = Sym->getKind(); 124 if (Modifier != MCSymbolRefExpr::VK_None) 125 return false; 126 switch (Kind) { 127 default: 128 llvm_unreachable("Invalid kind!"); 129 case VK_PPC_LO: 130 Modifier = MCSymbolRefExpr::VK_PPC_LO; 131 break; 132 case VK_PPC_HI: 133 Modifier = MCSymbolRefExpr::VK_PPC_HI; 134 break; 135 case VK_PPC_HA: 136 Modifier = MCSymbolRefExpr::VK_PPC_HA; 137 break; 138 case VK_PPC_HIGH: 139 Modifier = MCSymbolRefExpr::VK_PPC_HIGH; 140 break; 141 case VK_PPC_HIGHA: 142 Modifier = MCSymbolRefExpr::VK_PPC_HIGHA; 143 break; 144 case VK_PPC_HIGHERA: 145 Modifier = MCSymbolRefExpr::VK_PPC_HIGHERA; 146 break; 147 case VK_PPC_HIGHER: 148 Modifier = MCSymbolRefExpr::VK_PPC_HIGHER; 149 break; 150 case VK_PPC_HIGHEST: 151 Modifier = MCSymbolRefExpr::VK_PPC_HIGHEST; 152 break; 153 case VK_PPC_HIGHESTA: 154 Modifier = MCSymbolRefExpr::VK_PPC_HIGHESTA; 155 break; 156 } 157 Sym = MCSymbolRefExpr::create(&Sym->getSymbol(), Modifier, Context); 158 Res = MCValue::get(Sym, Value.getSymB(), Value.getConstant()); 159 } 160 161 return true; 162 } 163 164 void PPCMCExpr::visitUsedExpr(MCStreamer &Streamer) const { 165 Streamer.visitUsedExpr(*getSubExpr()); 166 } 167