1198090Srdivacky//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// 2198090Srdivacky// 3198090Srdivacky// The LLVM Compiler Infrastructure 4198090Srdivacky// 5198090Srdivacky// This file is distributed under the University of Illinois Open Source 6198090Srdivacky// License. See LICENSE.TXT for details. 7198090Srdivacky// 8198090Srdivacky//===----------------------------------------------------------------------===// 9198090Srdivacky 10206083Srdivacky#define DEBUG_TYPE "mcexpr" 11198090Srdivacky#include "llvm/MC/MCExpr.h" 12206083Srdivacky#include "llvm/ADT/Statistic.h" 13205218Srdivacky#include "llvm/ADT/StringSwitch.h" 14205218Srdivacky#include "llvm/MC/MCAsmLayout.h" 15205218Srdivacky#include "llvm/MC/MCAssembler.h" 16198090Srdivacky#include "llvm/MC/MCContext.h" 17234353Sdim#include "llvm/MC/MCObjectWriter.h" 18198090Srdivacky#include "llvm/MC/MCSymbol.h" 19198090Srdivacky#include "llvm/MC/MCValue.h" 20202375Srdivacky#include "llvm/Support/Debug.h" 21234353Sdim#include "llvm/Support/ErrorHandling.h" 22198090Srdivacky#include "llvm/Support/raw_ostream.h" 23198090Srdivackyusing namespace llvm; 24198090Srdivacky 25206083Srdivackynamespace { 26206083Srdivackynamespace stats { 27206083SrdivackySTATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); 28206083Srdivacky} 29206083Srdivacky} 30206083Srdivacky 31202878Srdivackyvoid MCExpr::print(raw_ostream &OS) const { 32198090Srdivacky switch (getKind()) { 33203954Srdivacky case MCExpr::Target: 34203954Srdivacky return cast<MCTargetExpr>(this)->PrintImpl(OS); 35198090Srdivacky case MCExpr::Constant: 36198090Srdivacky OS << cast<MCConstantExpr>(*this).getValue(); 37198090Srdivacky return; 38198090Srdivacky 39198090Srdivacky case MCExpr::SymbolRef: { 40205218Srdivacky const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); 41205218Srdivacky const MCSymbol &Sym = SRE.getSymbol(); 42218893Sdim // Parenthesize names that start with $ so that they don't look like 43218893Sdim // absolute names. 44218893Sdim bool UseParens = Sym.getName()[0] == '$'; 45218893Sdim if (UseParens) 46202878Srdivacky OS << '(' << Sym << ')'; 47202878Srdivacky else 48202878Srdivacky OS << Sym; 49205218Srdivacky 50249423Sdim if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_NONE || 51249423Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT || 52218893Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD || 53218893Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT || 54218893Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF || 55218893Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF || 56234353Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF || 57243830Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET1 || 58249423Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2 || 59249423Sdim SRE.getKind() == MCSymbolRefExpr::VK_ARM_PREL31) 60218893Sdim OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); 61263508Sdim else if (SRE.getKind() != MCSymbolRefExpr::VK_None) 62205218Srdivacky OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); 63205218Srdivacky 64198090Srdivacky return; 65198090Srdivacky } 66198090Srdivacky 67198090Srdivacky case MCExpr::Unary: { 68198090Srdivacky const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 69198090Srdivacky switch (UE.getOpcode()) { 70198090Srdivacky case MCUnaryExpr::LNot: OS << '!'; break; 71198090Srdivacky case MCUnaryExpr::Minus: OS << '-'; break; 72198090Srdivacky case MCUnaryExpr::Not: OS << '~'; break; 73198090Srdivacky case MCUnaryExpr::Plus: OS << '+'; break; 74198090Srdivacky } 75202878Srdivacky OS << *UE.getSubExpr(); 76198090Srdivacky return; 77198090Srdivacky } 78198090Srdivacky 79198090Srdivacky case MCExpr::Binary: { 80198090Srdivacky const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 81205407Srdivacky 82198090Srdivacky // Only print parens around the LHS if it is non-trivial. 83198090Srdivacky if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 84202878Srdivacky OS << *BE.getLHS(); 85198090Srdivacky } else { 86202878Srdivacky OS << '(' << *BE.getLHS() << ')'; 87198090Srdivacky } 88205407Srdivacky 89198090Srdivacky switch (BE.getOpcode()) { 90198090Srdivacky case MCBinaryExpr::Add: 91198090Srdivacky // Print "X-42" instead of "X+-42". 92198090Srdivacky if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 93198090Srdivacky if (RHSC->getValue() < 0) { 94198090Srdivacky OS << RHSC->getValue(); 95198090Srdivacky return; 96198090Srdivacky } 97198090Srdivacky } 98205407Srdivacky 99198090Srdivacky OS << '+'; 100198090Srdivacky break; 101198090Srdivacky case MCBinaryExpr::And: OS << '&'; break; 102198090Srdivacky case MCBinaryExpr::Div: OS << '/'; break; 103198090Srdivacky case MCBinaryExpr::EQ: OS << "=="; break; 104198090Srdivacky case MCBinaryExpr::GT: OS << '>'; break; 105198090Srdivacky case MCBinaryExpr::GTE: OS << ">="; break; 106198090Srdivacky case MCBinaryExpr::LAnd: OS << "&&"; break; 107198090Srdivacky case MCBinaryExpr::LOr: OS << "||"; break; 108198090Srdivacky case MCBinaryExpr::LT: OS << '<'; break; 109198090Srdivacky case MCBinaryExpr::LTE: OS << "<="; break; 110198090Srdivacky case MCBinaryExpr::Mod: OS << '%'; break; 111198090Srdivacky case MCBinaryExpr::Mul: OS << '*'; break; 112198090Srdivacky case MCBinaryExpr::NE: OS << "!="; break; 113198090Srdivacky case MCBinaryExpr::Or: OS << '|'; break; 114198090Srdivacky case MCBinaryExpr::Shl: OS << "<<"; break; 115198090Srdivacky case MCBinaryExpr::Shr: OS << ">>"; break; 116198090Srdivacky case MCBinaryExpr::Sub: OS << '-'; break; 117198090Srdivacky case MCBinaryExpr::Xor: OS << '^'; break; 118198090Srdivacky } 119205407Srdivacky 120198090Srdivacky // Only print parens around the LHS if it is non-trivial. 121198090Srdivacky if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 122202878Srdivacky OS << *BE.getRHS(); 123198090Srdivacky } else { 124202878Srdivacky OS << '(' << *BE.getRHS() << ')'; 125198090Srdivacky } 126198090Srdivacky return; 127198090Srdivacky } 128198090Srdivacky } 129198090Srdivacky 130234353Sdim llvm_unreachable("Invalid expression kind!"); 131198090Srdivacky} 132198090Srdivacky 133243830Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 134198090Srdivackyvoid MCExpr::dump() const { 135202878Srdivacky print(dbgs()); 136202375Srdivacky dbgs() << '\n'; 137198090Srdivacky} 138243830Sdim#endif 139198090Srdivacky 140198090Srdivacky/* *** */ 141198090Srdivacky 142198090Srdivackyconst MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, 143198090Srdivacky const MCExpr *RHS, MCContext &Ctx) { 144198090Srdivacky return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); 145198090Srdivacky} 146198090Srdivacky 147198090Srdivackyconst MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, 148198090Srdivacky MCContext &Ctx) { 149198090Srdivacky return new (Ctx) MCUnaryExpr(Opc, Expr); 150198090Srdivacky} 151198090Srdivacky 152198090Srdivackyconst MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { 153198090Srdivacky return new (Ctx) MCConstantExpr(Value); 154198090Srdivacky} 155198090Srdivacky 156205218Srdivacky/* *** */ 157205218Srdivacky 158198090Srdivackyconst MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, 159205218Srdivacky VariantKind Kind, 160198090Srdivacky MCContext &Ctx) { 161205218Srdivacky return new (Ctx) MCSymbolRefExpr(Sym, Kind); 162198090Srdivacky} 163198090Srdivacky 164205218Srdivackyconst MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, 165205218Srdivacky MCContext &Ctx) { 166205218Srdivacky return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); 167198090Srdivacky} 168198090Srdivacky 169205218SrdivackyStringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 170205218Srdivacky switch (Kind) { 171205218Srdivacky case VK_Invalid: return "<<invalid>>"; 172205218Srdivacky case VK_None: return "<<none>>"; 173205218Srdivacky 174205218Srdivacky case VK_GOT: return "GOT"; 175205218Srdivacky case VK_GOTOFF: return "GOTOFF"; 176205218Srdivacky case VK_GOTPCREL: return "GOTPCREL"; 177205218Srdivacky case VK_GOTTPOFF: return "GOTTPOFF"; 178205218Srdivacky case VK_INDNTPOFF: return "INDNTPOFF"; 179205218Srdivacky case VK_NTPOFF: return "NTPOFF"; 180218893Sdim case VK_GOTNTPOFF: return "GOTNTPOFF"; 181205218Srdivacky case VK_PLT: return "PLT"; 182205218Srdivacky case VK_TLSGD: return "TLSGD"; 183218893Sdim case VK_TLSLD: return "TLSLD"; 184218893Sdim case VK_TLSLDM: return "TLSLDM"; 185205218Srdivacky case VK_TPOFF: return "TPOFF"; 186218893Sdim case VK_DTPOFF: return "DTPOFF"; 187208599Srdivacky case VK_TLVP: return "TLVP"; 188249423Sdim case VK_SECREL: return "SECREL32"; 189249423Sdim case VK_ARM_NONE: return "(NONE)"; 190218893Sdim case VK_ARM_PLT: return "(PLT)"; 191218893Sdim case VK_ARM_GOT: return "(GOT)"; 192218893Sdim case VK_ARM_GOTOFF: return "(GOTOFF)"; 193218893Sdim case VK_ARM_TPOFF: return "(tpoff)"; 194218893Sdim case VK_ARM_GOTTPOFF: return "(gottpoff)"; 195218893Sdim case VK_ARM_TLSGD: return "(tlsgd)"; 196234353Sdim case VK_ARM_TARGET1: return "(target1)"; 197243830Sdim case VK_ARM_TARGET2: return "(target2)"; 198249423Sdim case VK_ARM_PREL31: return "(prel31)"; 199263508Sdim case VK_PPC_LO: return "l"; 200263508Sdim case VK_PPC_HI: return "h"; 201263508Sdim case VK_PPC_HA: return "ha"; 202263508Sdim case VK_PPC_HIGHER: return "higher"; 203263508Sdim case VK_PPC_HIGHERA: return "highera"; 204263508Sdim case VK_PPC_HIGHEST: return "highest"; 205263508Sdim case VK_PPC_HIGHESTA: return "highesta"; 206263508Sdim case VK_PPC_GOT_LO: return "got@l"; 207263508Sdim case VK_PPC_GOT_HI: return "got@h"; 208263508Sdim case VK_PPC_GOT_HA: return "got@ha"; 209263508Sdim case VK_PPC_TOCBASE: return "tocbase"; 210263508Sdim case VK_PPC_TOC: return "toc"; 211263508Sdim case VK_PPC_TOC_LO: return "toc@l"; 212263508Sdim case VK_PPC_TOC_HI: return "toc@h"; 213263508Sdim case VK_PPC_TOC_HA: return "toc@ha"; 214263508Sdim case VK_PPC_DTPMOD: return "dtpmod"; 215263508Sdim case VK_PPC_TPREL: return "tprel"; 216263508Sdim case VK_PPC_TPREL_LO: return "tprel@l"; 217263508Sdim case VK_PPC_TPREL_HI: return "tprel@h"; 218263508Sdim case VK_PPC_TPREL_HA: return "tprel@ha"; 219263508Sdim case VK_PPC_TPREL_HIGHER: return "tprel@higher"; 220263508Sdim case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; 221263508Sdim case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; 222263508Sdim case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; 223263508Sdim case VK_PPC_DTPREL: return "dtprel"; 224263508Sdim case VK_PPC_DTPREL_LO: return "dtprel@l"; 225263508Sdim case VK_PPC_DTPREL_HI: return "dtprel@h"; 226263508Sdim case VK_PPC_DTPREL_HA: return "dtprel@ha"; 227263508Sdim case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; 228263508Sdim case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; 229263508Sdim case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; 230263508Sdim case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; 231263508Sdim case VK_PPC_GOT_TPREL: return "got@tprel"; 232263508Sdim case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; 233263508Sdim case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; 234263508Sdim case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; 235263508Sdim case VK_PPC_GOT_DTPREL: return "got@dtprel"; 236263508Sdim case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; 237263508Sdim case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; 238263508Sdim case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; 239249423Sdim case VK_PPC_TLS: return "tls"; 240263508Sdim case VK_PPC_GOT_TLSGD: return "got@tlsgd"; 241263508Sdim case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; 242263508Sdim case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; 243263508Sdim case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; 244249423Sdim case VK_PPC_TLSGD: return "tlsgd"; 245263508Sdim case VK_PPC_GOT_TLSLD: return "got@tlsld"; 246263508Sdim case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 247263508Sdim case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; 248263508Sdim case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 249249423Sdim case VK_PPC_TLSLD: return "tlsld"; 250234353Sdim case VK_Mips_GPREL: return "GPREL"; 251234353Sdim case VK_Mips_GOT_CALL: return "GOT_CALL"; 252234353Sdim case VK_Mips_GOT16: return "GOT16"; 253234353Sdim case VK_Mips_GOT: return "GOT"; 254234353Sdim case VK_Mips_ABS_HI: return "ABS_HI"; 255234353Sdim case VK_Mips_ABS_LO: return "ABS_LO"; 256234353Sdim case VK_Mips_TLSGD: return "TLSGD"; 257234353Sdim case VK_Mips_TLSLDM: return "TLSLDM"; 258234353Sdim case VK_Mips_DTPREL_HI: return "DTPREL_HI"; 259234353Sdim case VK_Mips_DTPREL_LO: return "DTPREL_LO"; 260234353Sdim case VK_Mips_GOTTPREL: return "GOTTPREL"; 261234353Sdim case VK_Mips_TPREL_HI: return "TPREL_HI"; 262234353Sdim case VK_Mips_TPREL_LO: return "TPREL_LO"; 263234353Sdim case VK_Mips_GPOFF_HI: return "GPOFF_HI"; 264234353Sdim case VK_Mips_GPOFF_LO: return "GPOFF_LO"; 265234353Sdim case VK_Mips_GOT_DISP: return "GOT_DISP"; 266234353Sdim case VK_Mips_GOT_PAGE: return "GOT_PAGE"; 267234353Sdim case VK_Mips_GOT_OFST: return "GOT_OFST"; 268239462Sdim case VK_Mips_HIGHER: return "HIGHER"; 269239462Sdim case VK_Mips_HIGHEST: return "HIGHEST"; 270244628Sdim case VK_Mips_GOT_HI16: return "GOT_HI16"; 271244628Sdim case VK_Mips_GOT_LO16: return "GOT_LO16"; 272244628Sdim case VK_Mips_CALL_HI16: return "CALL_HI16"; 273244628Sdim case VK_Mips_CALL_LO16: return "CALL_LO16"; 274251662Sdim case VK_COFF_IMGREL32: return "IMGREL32"; 275205218Srdivacky } 276234353Sdim llvm_unreachable("Invalid variant kind"); 277205218Srdivacky} 278205218Srdivacky 279205218SrdivackyMCSymbolRefExpr::VariantKind 280205218SrdivackyMCSymbolRefExpr::getVariantKindForName(StringRef Name) { 281205218Srdivacky return StringSwitch<VariantKind>(Name) 282205218Srdivacky .Case("GOT", VK_GOT) 283218893Sdim .Case("got", VK_GOT) 284205218Srdivacky .Case("GOTOFF", VK_GOTOFF) 285218893Sdim .Case("gotoff", VK_GOTOFF) 286205218Srdivacky .Case("GOTPCREL", VK_GOTPCREL) 287218893Sdim .Case("gotpcrel", VK_GOTPCREL) 288205218Srdivacky .Case("GOTTPOFF", VK_GOTTPOFF) 289218893Sdim .Case("gottpoff", VK_GOTTPOFF) 290205218Srdivacky .Case("INDNTPOFF", VK_INDNTPOFF) 291218893Sdim .Case("indntpoff", VK_INDNTPOFF) 292205218Srdivacky .Case("NTPOFF", VK_NTPOFF) 293218893Sdim .Case("ntpoff", VK_NTPOFF) 294218893Sdim .Case("GOTNTPOFF", VK_GOTNTPOFF) 295218893Sdim .Case("gotntpoff", VK_GOTNTPOFF) 296205218Srdivacky .Case("PLT", VK_PLT) 297218893Sdim .Case("plt", VK_PLT) 298205218Srdivacky .Case("TLSGD", VK_TLSGD) 299218893Sdim .Case("tlsgd", VK_TLSGD) 300218893Sdim .Case("TLSLD", VK_TLSLD) 301218893Sdim .Case("tlsld", VK_TLSLD) 302218893Sdim .Case("TLSLDM", VK_TLSLDM) 303218893Sdim .Case("tlsldm", VK_TLSLDM) 304205218Srdivacky .Case("TPOFF", VK_TPOFF) 305218893Sdim .Case("tpoff", VK_TPOFF) 306218893Sdim .Case("DTPOFF", VK_DTPOFF) 307218893Sdim .Case("dtpoff", VK_DTPOFF) 308208599Srdivacky .Case("TLVP", VK_TLVP) 309218893Sdim .Case("tlvp", VK_TLVP) 310251662Sdim .Case("IMGREL", VK_COFF_IMGREL32) 311251662Sdim .Case("imgrel", VK_COFF_IMGREL32) 312251662Sdim .Case("SECREL32", VK_SECREL) 313251662Sdim .Case("secrel32", VK_SECREL) 314263508Sdim .Case("L", VK_PPC_LO) 315263508Sdim .Case("l", VK_PPC_LO) 316263508Sdim .Case("H", VK_PPC_HI) 317263508Sdim .Case("h", VK_PPC_HI) 318263508Sdim .Case("HA", VK_PPC_HA) 319263508Sdim .Case("ha", VK_PPC_HA) 320263508Sdim .Case("HIGHER", VK_PPC_HIGHER) 321263508Sdim .Case("higher", VK_PPC_HIGHER) 322263508Sdim .Case("HIGHERA", VK_PPC_HIGHERA) 323263508Sdim .Case("highera", VK_PPC_HIGHERA) 324263508Sdim .Case("HIGHEST", VK_PPC_HIGHEST) 325263508Sdim .Case("highest", VK_PPC_HIGHEST) 326263508Sdim .Case("HIGHESTA", VK_PPC_HIGHESTA) 327263508Sdim .Case("highesta", VK_PPC_HIGHESTA) 328263508Sdim .Case("GOT@L", VK_PPC_GOT_LO) 329263508Sdim .Case("got@l", VK_PPC_GOT_LO) 330263508Sdim .Case("GOT@H", VK_PPC_GOT_HI) 331263508Sdim .Case("got@h", VK_PPC_GOT_HI) 332263508Sdim .Case("GOT@HA", VK_PPC_GOT_HA) 333263508Sdim .Case("got@ha", VK_PPC_GOT_HA) 334263508Sdim .Case("TOCBASE", VK_PPC_TOCBASE) 335263508Sdim .Case("tocbase", VK_PPC_TOCBASE) 336263508Sdim .Case("TOC", VK_PPC_TOC) 337263508Sdim .Case("toc", VK_PPC_TOC) 338263508Sdim .Case("TOC@L", VK_PPC_TOC_LO) 339263508Sdim .Case("toc@l", VK_PPC_TOC_LO) 340263508Sdim .Case("TOC@H", VK_PPC_TOC_HI) 341263508Sdim .Case("toc@h", VK_PPC_TOC_HI) 342263508Sdim .Case("TOC@HA", VK_PPC_TOC_HA) 343263508Sdim .Case("toc@ha", VK_PPC_TOC_HA) 344251662Sdim .Case("TLS", VK_PPC_TLS) 345251662Sdim .Case("tls", VK_PPC_TLS) 346263508Sdim .Case("DTPMOD", VK_PPC_DTPMOD) 347263508Sdim .Case("dtpmod", VK_PPC_DTPMOD) 348263508Sdim .Case("TPREL", VK_PPC_TPREL) 349263508Sdim .Case("tprel", VK_PPC_TPREL) 350263508Sdim .Case("TPREL@L", VK_PPC_TPREL_LO) 351263508Sdim .Case("tprel@l", VK_PPC_TPREL_LO) 352263508Sdim .Case("TPREL@H", VK_PPC_TPREL_HI) 353263508Sdim .Case("tprel@h", VK_PPC_TPREL_HI) 354263508Sdim .Case("TPREL@HA", VK_PPC_TPREL_HA) 355263508Sdim .Case("tprel@ha", VK_PPC_TPREL_HA) 356263508Sdim .Case("TPREL@HIGHER", VK_PPC_TPREL_HIGHER) 357263508Sdim .Case("tprel@higher", VK_PPC_TPREL_HIGHER) 358263508Sdim .Case("TPREL@HIGHERA", VK_PPC_TPREL_HIGHERA) 359263508Sdim .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) 360263508Sdim .Case("TPREL@HIGHEST", VK_PPC_TPREL_HIGHEST) 361263508Sdim .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) 362263508Sdim .Case("TPREL@HIGHESTA", VK_PPC_TPREL_HIGHESTA) 363263508Sdim .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) 364263508Sdim .Case("DTPREL", VK_PPC_DTPREL) 365263508Sdim .Case("dtprel", VK_PPC_DTPREL) 366263508Sdim .Case("DTPREL@L", VK_PPC_DTPREL_LO) 367263508Sdim .Case("dtprel@l", VK_PPC_DTPREL_LO) 368263508Sdim .Case("DTPREL@H", VK_PPC_DTPREL_HI) 369263508Sdim .Case("dtprel@h", VK_PPC_DTPREL_HI) 370263508Sdim .Case("DTPREL@HA", VK_PPC_DTPREL_HA) 371263508Sdim .Case("dtprel@ha", VK_PPC_DTPREL_HA) 372263508Sdim .Case("DTPREL@HIGHER", VK_PPC_DTPREL_HIGHER) 373263508Sdim .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) 374263508Sdim .Case("DTPREL@HIGHERA", VK_PPC_DTPREL_HIGHERA) 375263508Sdim .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) 376263508Sdim .Case("DTPREL@HIGHEST", VK_PPC_DTPREL_HIGHEST) 377263508Sdim .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) 378263508Sdim .Case("DTPREL@HIGHESTA", VK_PPC_DTPREL_HIGHESTA) 379263508Sdim .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) 380263508Sdim .Case("GOT@TPREL", VK_PPC_GOT_TPREL) 381263508Sdim .Case("got@tprel", VK_PPC_GOT_TPREL) 382263508Sdim .Case("GOT@TPREL@L", VK_PPC_GOT_TPREL_LO) 383263508Sdim .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 384263508Sdim .Case("GOT@TPREL@H", VK_PPC_GOT_TPREL_HI) 385263508Sdim .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) 386263508Sdim .Case("GOT@TPREL@HA", VK_PPC_GOT_TPREL_HA) 387263508Sdim .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 388263508Sdim .Case("GOT@DTPREL", VK_PPC_GOT_DTPREL) 389263508Sdim .Case("got@dtprel", VK_PPC_GOT_DTPREL) 390263508Sdim .Case("GOT@DTPREL@L", VK_PPC_GOT_DTPREL_LO) 391263508Sdim .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) 392263508Sdim .Case("GOT@DTPREL@H", VK_PPC_GOT_DTPREL_HI) 393263508Sdim .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) 394263508Sdim .Case("GOT@DTPREL@HA", VK_PPC_GOT_DTPREL_HA) 395263508Sdim .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) 396263508Sdim .Case("GOT@TLSGD", VK_PPC_GOT_TLSGD) 397263508Sdim .Case("got@tlsgd", VK_PPC_GOT_TLSGD) 398263508Sdim .Case("GOT@TLSGD@L", VK_PPC_GOT_TLSGD_LO) 399263508Sdim .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 400263508Sdim .Case("GOT@TLSGD@H", VK_PPC_GOT_TLSGD_HI) 401263508Sdim .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) 402263508Sdim .Case("GOT@TLSGD@HA", VK_PPC_GOT_TLSGD_HA) 403263508Sdim .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 404263508Sdim .Case("GOT@TLSLD", VK_PPC_GOT_TLSLD) 405263508Sdim .Case("got@tlsld", VK_PPC_GOT_TLSLD) 406263508Sdim .Case("GOT@TLSLD@L", VK_PPC_GOT_TLSLD_LO) 407263508Sdim .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 408263508Sdim .Case("GOT@TLSLD@H", VK_PPC_GOT_TLSLD_HI) 409263508Sdim .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) 410263508Sdim .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA) 411263508Sdim .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 412205218Srdivacky .Default(VK_Invalid); 413205218Srdivacky} 414205218Srdivacky 415205218Srdivacky/* *** */ 416205218Srdivacky 417243830Sdimvoid MCTargetExpr::anchor() {} 418198090Srdivacky 419198090Srdivacky/* *** */ 420198090Srdivacky 421218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { 422218893Sdim return EvaluateAsAbsolute(Res, 0, 0, 0); 423218893Sdim} 424218893Sdim 425218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, 426218893Sdim const MCAsmLayout &Layout) const { 427218893Sdim return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0); 428218893Sdim} 429218893Sdim 430218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, 431218893Sdim const MCAsmLayout &Layout, 432218893Sdim const SectionAddrMap &Addrs) const { 433218893Sdim return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs); 434218893Sdim} 435218893Sdim 436218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 437218893Sdim return EvaluateAsAbsolute(Res, &Asm, 0, 0); 438218893Sdim} 439218893Sdim 440218893Sdimbool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 441218893Sdim const MCAsmLayout *Layout, 442218893Sdim const SectionAddrMap *Addrs) const { 443198090Srdivacky MCValue Value; 444205407Srdivacky 445206083Srdivacky // Fast path constants. 446206083Srdivacky if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 447206083Srdivacky Res = CE->getValue(); 448206083Srdivacky return true; 449206083Srdivacky } 450206083Srdivacky 451218893Sdim // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us 452218893Sdim // absolutize differences across sections and that is what the MachO writer 453218893Sdim // uses Addrs for. 454218893Sdim bool IsRelocatable = 455218893Sdim EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs); 456198090Srdivacky 457218893Sdim // Record the current value. 458198090Srdivacky Res = Value.getConstant(); 459218893Sdim 460218893Sdim return IsRelocatable && Value.isAbsolute(); 461198090Srdivacky} 462198090Srdivacky 463218893Sdim/// \brief Helper method for \see EvaluateSymbolAdd(). 464218893Sdimstatic void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, 465218893Sdim const MCAsmLayout *Layout, 466218893Sdim const SectionAddrMap *Addrs, 467218893Sdim bool InSet, 468218893Sdim const MCSymbolRefExpr *&A, 469218893Sdim const MCSymbolRefExpr *&B, 470218893Sdim int64_t &Addend) { 471218893Sdim if (!A || !B) 472218893Sdim return; 473218893Sdim 474218893Sdim const MCSymbol &SA = A->getSymbol(); 475218893Sdim const MCSymbol &SB = B->getSymbol(); 476218893Sdim 477218893Sdim if (SA.isUndefined() || SB.isUndefined()) 478218893Sdim return; 479218893Sdim 480218893Sdim if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 481218893Sdim return; 482218893Sdim 483218893Sdim MCSymbolData &AD = Asm->getSymbolData(SA); 484218893Sdim MCSymbolData &BD = Asm->getSymbolData(SB); 485218893Sdim 486218893Sdim if (AD.getFragment() == BD.getFragment()) { 487218893Sdim Addend += (AD.getOffset() - BD.getOffset()); 488218893Sdim 489221345Sdim // Pointers to Thumb symbols need to have their low-bit set to allow 490221345Sdim // for interworking. 491221345Sdim if (Asm->isThumbFunc(&SA)) 492221345Sdim Addend |= 1; 493221345Sdim 494218893Sdim // Clear the symbol expr pointers to indicate we have folded these 495218893Sdim // operands. 496218893Sdim A = B = 0; 497218893Sdim return; 498218893Sdim } 499218893Sdim 500218893Sdim if (!Layout) 501218893Sdim return; 502218893Sdim 503218893Sdim const MCSectionData &SecA = *AD.getFragment()->getParent(); 504218893Sdim const MCSectionData &SecB = *BD.getFragment()->getParent(); 505218893Sdim 506218893Sdim if ((&SecA != &SecB) && !Addrs) 507218893Sdim return; 508218893Sdim 509218893Sdim // Eagerly evaluate. 510218893Sdim Addend += (Layout->getSymbolOffset(&Asm->getSymbolData(A->getSymbol())) - 511218893Sdim Layout->getSymbolOffset(&Asm->getSymbolData(B->getSymbol()))); 512218893Sdim if (Addrs && (&SecA != &SecB)) 513218893Sdim Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 514218893Sdim 515234353Sdim // Pointers to Thumb symbols need to have their low-bit set to allow 516234353Sdim // for interworking. 517234353Sdim if (Asm->isThumbFunc(&SA)) 518234353Sdim Addend |= 1; 519234353Sdim 520218893Sdim // Clear the symbol expr pointers to indicate we have folded these 521218893Sdim // operands. 522218893Sdim A = B = 0; 523218893Sdim} 524218893Sdim 525218893Sdim/// \brief Evaluate the result of an add between (conceptually) two MCValues. 526218893Sdim/// 527218893Sdim/// This routine conceptually attempts to construct an MCValue: 528218893Sdim/// Result = (Result_A - Result_B + Result_Cst) 529218893Sdim/// from two MCValue's LHS and RHS where 530218893Sdim/// Result = LHS + RHS 531218893Sdim/// and 532218893Sdim/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 533218893Sdim/// 534218893Sdim/// This routine attempts to aggresively fold the operands such that the result 535218893Sdim/// is representable in an MCValue, but may not always succeed. 536218893Sdim/// 537218893Sdim/// \returns True on success, false if the result is not representable in an 538218893Sdim/// MCValue. 539218893Sdim 540218893Sdim/// NOTE: It is really important to have both the Asm and Layout arguments. 541218893Sdim/// They might look redundant, but this function can be used before layout 542218893Sdim/// is done (see the object streamer for example) and having the Asm argument 543218893Sdim/// lets us avoid relaxations early. 544218893Sdimstatic bool EvaluateSymbolicAdd(const MCAssembler *Asm, 545218893Sdim const MCAsmLayout *Layout, 546218893Sdim const SectionAddrMap *Addrs, 547218893Sdim bool InSet, 548218893Sdim const MCValue &LHS,const MCSymbolRefExpr *RHS_A, 549205407Srdivacky const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, 550198090Srdivacky MCValue &Res) { 551218893Sdim // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 552218893Sdim // about dealing with modifiers. This will ultimately bite us, one day. 553218893Sdim const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 554218893Sdim const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 555218893Sdim int64_t LHS_Cst = LHS.getConstant(); 556218893Sdim 557218893Sdim // Fold the result constant immediately. 558218893Sdim int64_t Result_Cst = LHS_Cst + RHS_Cst; 559218893Sdim 560218893Sdim assert((!Layout || Asm) && 561218893Sdim "Must have an assembler object if layout is given!"); 562218893Sdim 563218893Sdim // If we have a layout, we can fold resolved differences. 564218893Sdim if (Asm) { 565218893Sdim // First, fold out any differences which are fully resolved. By 566218893Sdim // reassociating terms in 567218893Sdim // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 568218893Sdim // we have the four possible differences: 569218893Sdim // (LHS_A - LHS_B), 570218893Sdim // (LHS_A - RHS_B), 571218893Sdim // (RHS_A - LHS_B), 572218893Sdim // (RHS_A - RHS_B). 573221345Sdim // Since we are attempting to be as aggressive as possible about folding, we 574218893Sdim // attempt to evaluate each possible alternative. 575218893Sdim AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 576218893Sdim Result_Cst); 577218893Sdim AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 578218893Sdim Result_Cst); 579218893Sdim AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 580218893Sdim Result_Cst); 581218893Sdim AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 582218893Sdim Result_Cst); 583218893Sdim } 584218893Sdim 585218893Sdim // We can't represent the addition or subtraction of two symbols. 586218893Sdim if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 587198090Srdivacky return false; 588198090Srdivacky 589218893Sdim // At this point, we have at most one additive symbol and one subtractive 590218893Sdim // symbol -- find them. 591218893Sdim const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 592218893Sdim const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 593218893Sdim 594218893Sdim // If we have a negated symbol, then we must have also have a non-negated 595218893Sdim // symbol in order to encode the expression. 596218893Sdim if (B && !A) 597218893Sdim return false; 598218893Sdim 599218893Sdim Res = MCValue::get(A, B, Result_Cst); 600198090Srdivacky return true; 601198090Srdivacky} 602198090Srdivacky 603205218Srdivackybool MCExpr::EvaluateAsRelocatable(MCValue &Res, 604218893Sdim const MCAsmLayout &Layout) const { 605218893Sdim return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout, 606218893Sdim 0, false); 607218893Sdim} 608218893Sdim 609218893Sdimbool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, 610218893Sdim const MCAssembler *Asm, 611218893Sdim const MCAsmLayout *Layout, 612218893Sdim const SectionAddrMap *Addrs, 613218893Sdim bool InSet) const { 614206083Srdivacky ++stats::MCExprEvaluate; 615206083Srdivacky 616198090Srdivacky switch (getKind()) { 617203954Srdivacky case Target: 618205218Srdivacky return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); 619205407Srdivacky 620198090Srdivacky case Constant: 621198090Srdivacky Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 622198090Srdivacky return true; 623198090Srdivacky 624198090Srdivacky case SymbolRef: { 625205407Srdivacky const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 626205407Srdivacky const MCSymbol &Sym = SRE->getSymbol(); 627198396Srdivacky 628198396Srdivacky // Evaluate recursively if this is a variable. 629218893Sdim if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { 630218893Sdim bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, 631218893Sdim Layout, 632218893Sdim Addrs, 633218893Sdim true); 634218893Sdim // If we failed to simplify this to a constant, let the target 635218893Sdim // handle it. 636218893Sdim if (Ret && !Res.getSymA() && !Res.getSymB()) 637218893Sdim return true; 638205218Srdivacky } 639205218Srdivacky 640205407Srdivacky Res = MCValue::get(SRE, 0, 0); 641198090Srdivacky return true; 642198090Srdivacky } 643198090Srdivacky 644198090Srdivacky case Unary: { 645198090Srdivacky const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 646198090Srdivacky MCValue Value; 647198090Srdivacky 648218893Sdim if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, 649218893Sdim Addrs, InSet)) 650198090Srdivacky return false; 651198090Srdivacky 652198090Srdivacky switch (AUE->getOpcode()) { 653198090Srdivacky case MCUnaryExpr::LNot: 654198090Srdivacky if (!Value.isAbsolute()) 655198090Srdivacky return false; 656198090Srdivacky Res = MCValue::get(!Value.getConstant()); 657198090Srdivacky break; 658198090Srdivacky case MCUnaryExpr::Minus: 659198090Srdivacky /// -(a - b + const) ==> (b - a - const) 660198090Srdivacky if (Value.getSymA() && !Value.getSymB()) 661198090Srdivacky return false; 662205407Srdivacky Res = MCValue::get(Value.getSymB(), Value.getSymA(), 663205407Srdivacky -Value.getConstant()); 664198090Srdivacky break; 665198090Srdivacky case MCUnaryExpr::Not: 666198090Srdivacky if (!Value.isAbsolute()) 667198090Srdivacky return false; 668205407Srdivacky Res = MCValue::get(~Value.getConstant()); 669198090Srdivacky break; 670198090Srdivacky case MCUnaryExpr::Plus: 671198090Srdivacky Res = Value; 672198090Srdivacky break; 673198090Srdivacky } 674198090Srdivacky 675198090Srdivacky return true; 676198090Srdivacky } 677198090Srdivacky 678198090Srdivacky case Binary: { 679198090Srdivacky const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 680198090Srdivacky MCValue LHSValue, RHSValue; 681205407Srdivacky 682218893Sdim if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, 683218893Sdim Addrs, InSet) || 684218893Sdim !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, 685218893Sdim Addrs, InSet)) 686198090Srdivacky return false; 687198090Srdivacky 688198090Srdivacky // We only support a few operations on non-constant expressions, handle 689198090Srdivacky // those first. 690198090Srdivacky if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 691198090Srdivacky switch (ABE->getOpcode()) { 692198090Srdivacky default: 693198090Srdivacky return false; 694198090Srdivacky case MCBinaryExpr::Sub: 695198090Srdivacky // Negate RHS and add. 696218893Sdim return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 697198090Srdivacky RHSValue.getSymB(), RHSValue.getSymA(), 698198090Srdivacky -RHSValue.getConstant(), 699198090Srdivacky Res); 700198090Srdivacky 701198090Srdivacky case MCBinaryExpr::Add: 702218893Sdim return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 703198090Srdivacky RHSValue.getSymA(), RHSValue.getSymB(), 704198090Srdivacky RHSValue.getConstant(), 705198090Srdivacky Res); 706198090Srdivacky } 707198090Srdivacky } 708198090Srdivacky 709198090Srdivacky // FIXME: We need target hooks for the evaluation. It may be limited in 710203954Srdivacky // width, and gas defines the result of comparisons and right shifts 711203954Srdivacky // differently from Apple as. 712198090Srdivacky int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 713198090Srdivacky int64_t Result = 0; 714198090Srdivacky switch (ABE->getOpcode()) { 715198090Srdivacky case MCBinaryExpr::Add: Result = LHS + RHS; break; 716198090Srdivacky case MCBinaryExpr::And: Result = LHS & RHS; break; 717198090Srdivacky case MCBinaryExpr::Div: Result = LHS / RHS; break; 718198090Srdivacky case MCBinaryExpr::EQ: Result = LHS == RHS; break; 719198090Srdivacky case MCBinaryExpr::GT: Result = LHS > RHS; break; 720198090Srdivacky case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 721198090Srdivacky case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 722198090Srdivacky case MCBinaryExpr::LOr: Result = LHS || RHS; break; 723198090Srdivacky case MCBinaryExpr::LT: Result = LHS < RHS; break; 724198090Srdivacky case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 725198090Srdivacky case MCBinaryExpr::Mod: Result = LHS % RHS; break; 726198090Srdivacky case MCBinaryExpr::Mul: Result = LHS * RHS; break; 727198090Srdivacky case MCBinaryExpr::NE: Result = LHS != RHS; break; 728198090Srdivacky case MCBinaryExpr::Or: Result = LHS | RHS; break; 729198090Srdivacky case MCBinaryExpr::Shl: Result = LHS << RHS; break; 730198090Srdivacky case MCBinaryExpr::Shr: Result = LHS >> RHS; break; 731198090Srdivacky case MCBinaryExpr::Sub: Result = LHS - RHS; break; 732198090Srdivacky case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 733198090Srdivacky } 734198090Srdivacky 735198090Srdivacky Res = MCValue::get(Result); 736198090Srdivacky return true; 737198090Srdivacky } 738198090Srdivacky } 739198090Srdivacky 740234353Sdim llvm_unreachable("Invalid assembly expression kind!"); 741198090Srdivacky} 742221345Sdim 743221345Sdimconst MCSection *MCExpr::FindAssociatedSection() const { 744221345Sdim switch (getKind()) { 745221345Sdim case Target: 746221345Sdim // We never look through target specific expressions. 747221345Sdim return cast<MCTargetExpr>(this)->FindAssociatedSection(); 748221345Sdim 749221345Sdim case Constant: 750221345Sdim return MCSymbol::AbsolutePseudoSection; 751221345Sdim 752221345Sdim case SymbolRef: { 753221345Sdim const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 754221345Sdim const MCSymbol &Sym = SRE->getSymbol(); 755221345Sdim 756221345Sdim if (Sym.isDefined()) 757221345Sdim return &Sym.getSection(); 758221345Sdim 759221345Sdim return 0; 760221345Sdim } 761221345Sdim 762221345Sdim case Unary: 763221345Sdim return cast<MCUnaryExpr>(this)->getSubExpr()->FindAssociatedSection(); 764221345Sdim 765221345Sdim case Binary: { 766221345Sdim const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 767221345Sdim const MCSection *LHS_S = BE->getLHS()->FindAssociatedSection(); 768221345Sdim const MCSection *RHS_S = BE->getRHS()->FindAssociatedSection(); 769221345Sdim 770221345Sdim // If either section is absolute, return the other. 771221345Sdim if (LHS_S == MCSymbol::AbsolutePseudoSection) 772221345Sdim return RHS_S; 773221345Sdim if (RHS_S == MCSymbol::AbsolutePseudoSection) 774221345Sdim return LHS_S; 775221345Sdim 776221345Sdim // Otherwise, return the first non-null section. 777221345Sdim return LHS_S ? LHS_S : RHS_S; 778221345Sdim } 779221345Sdim } 780221345Sdim 781234353Sdim llvm_unreachable("Invalid assembly expression kind!"); 782221345Sdim} 783