MCExpr.cpp revision d2849572463da994c685b3bd7a60d5a7566c01e3
1//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#define DEBUG_TYPE "mcexpr" 11#include "llvm/MC/MCExpr.h" 12#include "llvm/ADT/Statistic.h" 13#include "llvm/ADT/StringSwitch.h" 14#include "llvm/MC/MCAsmLayout.h" 15#include "llvm/MC/MCAssembler.h" 16#include "llvm/MC/MCContext.h" 17#include "llvm/MC/MCObjectWriter.h" 18#include "llvm/MC/MCSymbol.h" 19#include "llvm/MC/MCValue.h" 20#include "llvm/Support/Debug.h" 21#include "llvm/Support/ErrorHandling.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace llvm; 24 25namespace { 26namespace stats { 27STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); 28} 29} 30 31void MCExpr::print(raw_ostream &OS) const { 32 switch (getKind()) { 33 case MCExpr::Target: 34 return cast<MCTargetExpr>(this)->PrintImpl(OS); 35 case MCExpr::Constant: 36 OS << cast<MCConstantExpr>(*this).getValue(); 37 return; 38 39 case MCExpr::SymbolRef: { 40 const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); 41 const MCSymbol &Sym = SRE.getSymbol(); 42 // Parenthesize names that start with $ so that they don't look like 43 // absolute names. 44 bool UseParens = Sym.getName()[0] == '$'; 45 if (UseParens) 46 OS << '(' << Sym << ')'; 47 else 48 OS << Sym; 49 50 if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_NONE || 51 SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT || 52 SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD || 53 SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT || 54 SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF || 55 SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF || 56 SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF || 57 SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET1 || 58 SRE.getKind() == MCSymbolRefExpr::VK_ARM_TARGET2 || 59 SRE.getKind() == MCSymbolRefExpr::VK_ARM_PREL31) 60 OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); 61 else if (SRE.getKind() != MCSymbolRefExpr::VK_None) 62 OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); 63 64 return; 65 } 66 67 case MCExpr::Unary: { 68 const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); 69 switch (UE.getOpcode()) { 70 case MCUnaryExpr::LNot: OS << '!'; break; 71 case MCUnaryExpr::Minus: OS << '-'; break; 72 case MCUnaryExpr::Not: OS << '~'; break; 73 case MCUnaryExpr::Plus: OS << '+'; break; 74 } 75 OS << *UE.getSubExpr(); 76 return; 77 } 78 79 case MCExpr::Binary: { 80 const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); 81 82 // Only print parens around the LHS if it is non-trivial. 83 if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { 84 OS << *BE.getLHS(); 85 } else { 86 OS << '(' << *BE.getLHS() << ')'; 87 } 88 89 switch (BE.getOpcode()) { 90 case MCBinaryExpr::Add: 91 // Print "X-42" instead of "X+-42". 92 if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { 93 if (RHSC->getValue() < 0) { 94 OS << RHSC->getValue(); 95 return; 96 } 97 } 98 99 OS << '+'; 100 break; 101 case MCBinaryExpr::And: OS << '&'; break; 102 case MCBinaryExpr::Div: OS << '/'; break; 103 case MCBinaryExpr::EQ: OS << "=="; break; 104 case MCBinaryExpr::GT: OS << '>'; break; 105 case MCBinaryExpr::GTE: OS << ">="; break; 106 case MCBinaryExpr::LAnd: OS << "&&"; break; 107 case MCBinaryExpr::LOr: OS << "||"; break; 108 case MCBinaryExpr::LT: OS << '<'; break; 109 case MCBinaryExpr::LTE: OS << "<="; break; 110 case MCBinaryExpr::Mod: OS << '%'; break; 111 case MCBinaryExpr::Mul: OS << '*'; break; 112 case MCBinaryExpr::NE: OS << "!="; break; 113 case MCBinaryExpr::Or: OS << '|'; break; 114 case MCBinaryExpr::Shl: OS << "<<"; break; 115 case MCBinaryExpr::Shr: OS << ">>"; break; 116 case MCBinaryExpr::Sub: OS << '-'; break; 117 case MCBinaryExpr::Xor: OS << '^'; break; 118 } 119 120 // Only print parens around the LHS if it is non-trivial. 121 if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { 122 OS << *BE.getRHS(); 123 } else { 124 OS << '(' << *BE.getRHS() << ')'; 125 } 126 return; 127 } 128 } 129 130 llvm_unreachable("Invalid expression kind!"); 131} 132 133#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 134void MCExpr::dump() const { 135 print(dbgs()); 136 dbgs() << '\n'; 137} 138#endif 139 140/* *** */ 141 142const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, 143 const MCExpr *RHS, MCContext &Ctx) { 144 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); 145} 146 147const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, 148 MCContext &Ctx) { 149 return new (Ctx) MCUnaryExpr(Opc, Expr); 150} 151 152const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { 153 return new (Ctx) MCConstantExpr(Value); 154} 155 156/* *** */ 157 158const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, 159 VariantKind Kind, 160 MCContext &Ctx) { 161 return new (Ctx) MCSymbolRefExpr(Sym, Kind); 162} 163 164const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, 165 MCContext &Ctx) { 166 return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); 167} 168 169StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { 170 switch (Kind) { 171 case VK_Invalid: return "<<invalid>>"; 172 case VK_None: return "<<none>>"; 173 174 case VK_GOT: return "GOT"; 175 case VK_GOTOFF: return "GOTOFF"; 176 case VK_GOTPCREL: return "GOTPCREL"; 177 case VK_GOTTPOFF: return "GOTTPOFF"; 178 case VK_INDNTPOFF: return "INDNTPOFF"; 179 case VK_NTPOFF: return "NTPOFF"; 180 case VK_GOTNTPOFF: return "GOTNTPOFF"; 181 case VK_PLT: return "PLT"; 182 case VK_TLSGD: return "TLSGD"; 183 case VK_TLSLD: return "TLSLD"; 184 case VK_TLSLDM: return "TLSLDM"; 185 case VK_TPOFF: return "TPOFF"; 186 case VK_DTPOFF: return "DTPOFF"; 187 case VK_TLVP: return "TLVP"; 188 case VK_SECREL: return "SECREL32"; 189 case VK_ARM_NONE: return "(NONE)"; 190 case VK_ARM_PLT: return "(PLT)"; 191 case VK_ARM_GOT: return "(GOT)"; 192 case VK_ARM_GOTOFF: return "(GOTOFF)"; 193 case VK_ARM_TPOFF: return "(tpoff)"; 194 case VK_ARM_GOTTPOFF: return "(gottpoff)"; 195 case VK_ARM_TLSGD: return "(tlsgd)"; 196 case VK_ARM_TARGET1: return "(target1)"; 197 case VK_ARM_TARGET2: return "(target2)"; 198 case VK_ARM_PREL31: return "(prel31)"; 199 case VK_PPC_LO: return "l"; 200 case VK_PPC_HI: return "h"; 201 case VK_PPC_HA: return "ha"; 202 case VK_PPC_TOCBASE: return "tocbase"; 203 case VK_PPC_TOC: return "toc"; 204 case VK_PPC_TOC_LO: return "toc@l"; 205 case VK_PPC_TOC_HA: return "toc@ha"; 206 case VK_PPC_TPREL_LO: return "tprel@l"; 207 case VK_PPC_TPREL_HA: return "tprel@ha"; 208 case VK_PPC_DTPREL_LO: return "dtprel@l"; 209 case VK_PPC_DTPREL_HA: return "dtprel@ha"; 210 case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; 211 case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; 212 case VK_PPC_TLS: return "tls"; 213 case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; 214 case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; 215 case VK_PPC_TLSGD: return "tlsgd"; 216 case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; 217 case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; 218 case VK_PPC_TLSLD: return "tlsld"; 219 case VK_Mips_GPREL: return "GPREL"; 220 case VK_Mips_GOT_CALL: return "GOT_CALL"; 221 case VK_Mips_GOT16: return "GOT16"; 222 case VK_Mips_GOT: return "GOT"; 223 case VK_Mips_ABS_HI: return "ABS_HI"; 224 case VK_Mips_ABS_LO: return "ABS_LO"; 225 case VK_Mips_TLSGD: return "TLSGD"; 226 case VK_Mips_TLSLDM: return "TLSLDM"; 227 case VK_Mips_DTPREL_HI: return "DTPREL_HI"; 228 case VK_Mips_DTPREL_LO: return "DTPREL_LO"; 229 case VK_Mips_GOTTPREL: return "GOTTPREL"; 230 case VK_Mips_TPREL_HI: return "TPREL_HI"; 231 case VK_Mips_TPREL_LO: return "TPREL_LO"; 232 case VK_Mips_GPOFF_HI: return "GPOFF_HI"; 233 case VK_Mips_GPOFF_LO: return "GPOFF_LO"; 234 case VK_Mips_GOT_DISP: return "GOT_DISP"; 235 case VK_Mips_GOT_PAGE: return "GOT_PAGE"; 236 case VK_Mips_GOT_OFST: return "GOT_OFST"; 237 case VK_Mips_HIGHER: return "HIGHER"; 238 case VK_Mips_HIGHEST: return "HIGHEST"; 239 case VK_Mips_GOT_HI16: return "GOT_HI16"; 240 case VK_Mips_GOT_LO16: return "GOT_LO16"; 241 case VK_Mips_CALL_HI16: return "CALL_HI16"; 242 case VK_Mips_CALL_LO16: return "CALL_LO16"; 243 case VK_COFF_IMGREL32: return "IMGREL32"; 244 } 245 llvm_unreachable("Invalid variant kind"); 246} 247 248MCSymbolRefExpr::VariantKind 249MCSymbolRefExpr::getVariantKindForName(StringRef Name) { 250 return StringSwitch<VariantKind>(Name) 251 .Case("GOT", VK_GOT) 252 .Case("got", VK_GOT) 253 .Case("GOTOFF", VK_GOTOFF) 254 .Case("gotoff", VK_GOTOFF) 255 .Case("GOTPCREL", VK_GOTPCREL) 256 .Case("gotpcrel", VK_GOTPCREL) 257 .Case("GOTTPOFF", VK_GOTTPOFF) 258 .Case("gottpoff", VK_GOTTPOFF) 259 .Case("INDNTPOFF", VK_INDNTPOFF) 260 .Case("indntpoff", VK_INDNTPOFF) 261 .Case("NTPOFF", VK_NTPOFF) 262 .Case("ntpoff", VK_NTPOFF) 263 .Case("GOTNTPOFF", VK_GOTNTPOFF) 264 .Case("gotntpoff", VK_GOTNTPOFF) 265 .Case("PLT", VK_PLT) 266 .Case("plt", VK_PLT) 267 .Case("TLSGD", VK_TLSGD) 268 .Case("tlsgd", VK_TLSGD) 269 .Case("TLSLD", VK_TLSLD) 270 .Case("tlsld", VK_TLSLD) 271 .Case("TLSLDM", VK_TLSLDM) 272 .Case("tlsldm", VK_TLSLDM) 273 .Case("TPOFF", VK_TPOFF) 274 .Case("tpoff", VK_TPOFF) 275 .Case("DTPOFF", VK_DTPOFF) 276 .Case("dtpoff", VK_DTPOFF) 277 .Case("TLVP", VK_TLVP) 278 .Case("tlvp", VK_TLVP) 279 .Case("IMGREL", VK_COFF_IMGREL32) 280 .Case("imgrel", VK_COFF_IMGREL32) 281 .Case("SECREL32", VK_SECREL) 282 .Case("secrel32", VK_SECREL) 283 .Case("L", VK_PPC_LO) 284 .Case("l", VK_PPC_LO) 285 .Case("H", VK_PPC_HI) 286 .Case("h", VK_PPC_HI) 287 .Case("HA", VK_PPC_HA) 288 .Case("ha", VK_PPC_HA) 289 .Case("TOCBASE", VK_PPC_TOCBASE) 290 .Case("tocbase", VK_PPC_TOCBASE) 291 .Case("TOC", VK_PPC_TOC) 292 .Case("toc", VK_PPC_TOC) 293 .Case("TOC@L", VK_PPC_TOC_LO) 294 .Case("toc@l", VK_PPC_TOC_LO) 295 .Case("TOC@HA", VK_PPC_TOC_HA) 296 .Case("toc@ha", VK_PPC_TOC_HA) 297 .Case("TLS", VK_PPC_TLS) 298 .Case("tls", VK_PPC_TLS) 299 .Case("TPREL@L", VK_PPC_TPREL_LO) 300 .Case("tprel@l", VK_PPC_TPREL_LO) 301 .Case("TPREL@HA", VK_PPC_TPREL_HA) 302 .Case("tprel@ha", VK_PPC_TPREL_HA) 303 .Case("DTPREL@L", VK_PPC_DTPREL_LO) 304 .Case("dtprel@l", VK_PPC_DTPREL_LO) 305 .Case("DTPREL@HA", VK_PPC_DTPREL_HA) 306 .Case("dtprel@ha", VK_PPC_DTPREL_HA) 307 .Case("GOT@TPREL@L", VK_PPC_GOT_TPREL_LO) 308 .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) 309 .Case("GOT@TPREL@HA", VK_PPC_GOT_TPREL_HA) 310 .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) 311 .Case("GOT@TLSGD@L", VK_PPC_GOT_TLSGD_LO) 312 .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) 313 .Case("GOT@TLSGD@HA", VK_PPC_GOT_TLSGD_HA) 314 .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) 315 .Case("GOT@TLSLD@L", VK_PPC_GOT_TLSLD_LO) 316 .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) 317 .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA) 318 .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) 319 .Default(VK_Invalid); 320} 321 322/* *** */ 323 324void MCTargetExpr::anchor() {} 325 326/* *** */ 327 328bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { 329 return EvaluateAsAbsolute(Res, 0, 0, 0); 330} 331 332bool MCExpr::EvaluateAsAbsolute(int64_t &Res, 333 const MCAsmLayout &Layout) const { 334 return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0); 335} 336 337bool MCExpr::EvaluateAsAbsolute(int64_t &Res, 338 const MCAsmLayout &Layout, 339 const SectionAddrMap &Addrs) const { 340 return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs); 341} 342 343bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { 344 return EvaluateAsAbsolute(Res, &Asm, 0, 0); 345} 346 347bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, 348 const MCAsmLayout *Layout, 349 const SectionAddrMap *Addrs) const { 350 MCValue Value; 351 352 // Fast path constants. 353 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { 354 Res = CE->getValue(); 355 return true; 356 } 357 358 // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us 359 // absolutize differences across sections and that is what the MachO writer 360 // uses Addrs for. 361 bool IsRelocatable = 362 EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs); 363 364 // Record the current value. 365 Res = Value.getConstant(); 366 367 return IsRelocatable && Value.isAbsolute(); 368} 369 370/// \brief Helper method for \see EvaluateSymbolAdd(). 371static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, 372 const MCAsmLayout *Layout, 373 const SectionAddrMap *Addrs, 374 bool InSet, 375 const MCSymbolRefExpr *&A, 376 const MCSymbolRefExpr *&B, 377 int64_t &Addend) { 378 if (!A || !B) 379 return; 380 381 const MCSymbol &SA = A->getSymbol(); 382 const MCSymbol &SB = B->getSymbol(); 383 384 if (SA.isUndefined() || SB.isUndefined()) 385 return; 386 387 if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) 388 return; 389 390 MCSymbolData &AD = Asm->getSymbolData(SA); 391 MCSymbolData &BD = Asm->getSymbolData(SB); 392 393 if (AD.getFragment() == BD.getFragment()) { 394 Addend += (AD.getOffset() - BD.getOffset()); 395 396 // Pointers to Thumb symbols need to have their low-bit set to allow 397 // for interworking. 398 if (Asm->isThumbFunc(&SA)) 399 Addend |= 1; 400 401 // Clear the symbol expr pointers to indicate we have folded these 402 // operands. 403 A = B = 0; 404 return; 405 } 406 407 if (!Layout) 408 return; 409 410 const MCSectionData &SecA = *AD.getFragment()->getParent(); 411 const MCSectionData &SecB = *BD.getFragment()->getParent(); 412 413 if ((&SecA != &SecB) && !Addrs) 414 return; 415 416 // Eagerly evaluate. 417 Addend += (Layout->getSymbolOffset(&Asm->getSymbolData(A->getSymbol())) - 418 Layout->getSymbolOffset(&Asm->getSymbolData(B->getSymbol()))); 419 if (Addrs && (&SecA != &SecB)) 420 Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); 421 422 // Pointers to Thumb symbols need to have their low-bit set to allow 423 // for interworking. 424 if (Asm->isThumbFunc(&SA)) 425 Addend |= 1; 426 427 // Clear the symbol expr pointers to indicate we have folded these 428 // operands. 429 A = B = 0; 430} 431 432/// \brief Evaluate the result of an add between (conceptually) two MCValues. 433/// 434/// This routine conceptually attempts to construct an MCValue: 435/// Result = (Result_A - Result_B + Result_Cst) 436/// from two MCValue's LHS and RHS where 437/// Result = LHS + RHS 438/// and 439/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 440/// 441/// This routine attempts to aggresively fold the operands such that the result 442/// is representable in an MCValue, but may not always succeed. 443/// 444/// \returns True on success, false if the result is not representable in an 445/// MCValue. 446 447/// NOTE: It is really important to have both the Asm and Layout arguments. 448/// They might look redundant, but this function can be used before layout 449/// is done (see the object streamer for example) and having the Asm argument 450/// lets us avoid relaxations early. 451static bool EvaluateSymbolicAdd(const MCAssembler *Asm, 452 const MCAsmLayout *Layout, 453 const SectionAddrMap *Addrs, 454 bool InSet, 455 const MCValue &LHS,const MCSymbolRefExpr *RHS_A, 456 const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, 457 MCValue &Res) { 458 // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy 459 // about dealing with modifiers. This will ultimately bite us, one day. 460 const MCSymbolRefExpr *LHS_A = LHS.getSymA(); 461 const MCSymbolRefExpr *LHS_B = LHS.getSymB(); 462 int64_t LHS_Cst = LHS.getConstant(); 463 464 // Fold the result constant immediately. 465 int64_t Result_Cst = LHS_Cst + RHS_Cst; 466 467 assert((!Layout || Asm) && 468 "Must have an assembler object if layout is given!"); 469 470 // If we have a layout, we can fold resolved differences. 471 if (Asm) { 472 // First, fold out any differences which are fully resolved. By 473 // reassociating terms in 474 // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). 475 // we have the four possible differences: 476 // (LHS_A - LHS_B), 477 // (LHS_A - RHS_B), 478 // (RHS_A - LHS_B), 479 // (RHS_A - RHS_B). 480 // Since we are attempting to be as aggressive as possible about folding, we 481 // attempt to evaluate each possible alternative. 482 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, 483 Result_Cst); 484 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, 485 Result_Cst); 486 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, 487 Result_Cst); 488 AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, 489 Result_Cst); 490 } 491 492 // We can't represent the addition or subtraction of two symbols. 493 if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) 494 return false; 495 496 // At this point, we have at most one additive symbol and one subtractive 497 // symbol -- find them. 498 const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; 499 const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; 500 501 // If we have a negated symbol, then we must have also have a non-negated 502 // symbol in order to encode the expression. 503 if (B && !A) 504 return false; 505 506 Res = MCValue::get(A, B, Result_Cst); 507 return true; 508} 509 510bool MCExpr::EvaluateAsRelocatable(MCValue &Res, 511 const MCAsmLayout &Layout) const { 512 return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout, 513 0, false); 514} 515 516bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, 517 const MCAssembler *Asm, 518 const MCAsmLayout *Layout, 519 const SectionAddrMap *Addrs, 520 bool InSet) const { 521 ++stats::MCExprEvaluate; 522 523 switch (getKind()) { 524 case Target: 525 return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout); 526 527 case Constant: 528 Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); 529 return true; 530 531 case SymbolRef: { 532 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 533 const MCSymbol &Sym = SRE->getSymbol(); 534 535 // Evaluate recursively if this is a variable. 536 if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { 537 bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, 538 Layout, 539 Addrs, 540 true); 541 // If we failed to simplify this to a constant, let the target 542 // handle it. 543 if (Ret && !Res.getSymA() && !Res.getSymB()) 544 return true; 545 } 546 547 Res = MCValue::get(SRE, 0, 0); 548 return true; 549 } 550 551 case Unary: { 552 const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); 553 MCValue Value; 554 555 if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, 556 Addrs, InSet)) 557 return false; 558 559 switch (AUE->getOpcode()) { 560 case MCUnaryExpr::LNot: 561 if (!Value.isAbsolute()) 562 return false; 563 Res = MCValue::get(!Value.getConstant()); 564 break; 565 case MCUnaryExpr::Minus: 566 /// -(a - b + const) ==> (b - a - const) 567 if (Value.getSymA() && !Value.getSymB()) 568 return false; 569 Res = MCValue::get(Value.getSymB(), Value.getSymA(), 570 -Value.getConstant()); 571 break; 572 case MCUnaryExpr::Not: 573 if (!Value.isAbsolute()) 574 return false; 575 Res = MCValue::get(~Value.getConstant()); 576 break; 577 case MCUnaryExpr::Plus: 578 Res = Value; 579 break; 580 } 581 582 return true; 583 } 584 585 case Binary: { 586 const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); 587 MCValue LHSValue, RHSValue; 588 589 if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, 590 Addrs, InSet) || 591 !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, 592 Addrs, InSet)) 593 return false; 594 595 // We only support a few operations on non-constant expressions, handle 596 // those first. 597 if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { 598 switch (ABE->getOpcode()) { 599 default: 600 return false; 601 case MCBinaryExpr::Sub: 602 // Negate RHS and add. 603 return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 604 RHSValue.getSymB(), RHSValue.getSymA(), 605 -RHSValue.getConstant(), 606 Res); 607 608 case MCBinaryExpr::Add: 609 return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, 610 RHSValue.getSymA(), RHSValue.getSymB(), 611 RHSValue.getConstant(), 612 Res); 613 } 614 } 615 616 // FIXME: We need target hooks for the evaluation. It may be limited in 617 // width, and gas defines the result of comparisons and right shifts 618 // differently from Apple as. 619 int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); 620 int64_t Result = 0; 621 switch (ABE->getOpcode()) { 622 case MCBinaryExpr::Add: Result = LHS + RHS; break; 623 case MCBinaryExpr::And: Result = LHS & RHS; break; 624 case MCBinaryExpr::Div: Result = LHS / RHS; break; 625 case MCBinaryExpr::EQ: Result = LHS == RHS; break; 626 case MCBinaryExpr::GT: Result = LHS > RHS; break; 627 case MCBinaryExpr::GTE: Result = LHS >= RHS; break; 628 case MCBinaryExpr::LAnd: Result = LHS && RHS; break; 629 case MCBinaryExpr::LOr: Result = LHS || RHS; break; 630 case MCBinaryExpr::LT: Result = LHS < RHS; break; 631 case MCBinaryExpr::LTE: Result = LHS <= RHS; break; 632 case MCBinaryExpr::Mod: Result = LHS % RHS; break; 633 case MCBinaryExpr::Mul: Result = LHS * RHS; break; 634 case MCBinaryExpr::NE: Result = LHS != RHS; break; 635 case MCBinaryExpr::Or: Result = LHS | RHS; break; 636 case MCBinaryExpr::Shl: Result = LHS << RHS; break; 637 case MCBinaryExpr::Shr: Result = LHS >> RHS; break; 638 case MCBinaryExpr::Sub: Result = LHS - RHS; break; 639 case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; 640 } 641 642 Res = MCValue::get(Result); 643 return true; 644 } 645 } 646 647 llvm_unreachable("Invalid assembly expression kind!"); 648} 649 650const MCSection *MCExpr::FindAssociatedSection() const { 651 switch (getKind()) { 652 case Target: 653 // We never look through target specific expressions. 654 return cast<MCTargetExpr>(this)->FindAssociatedSection(); 655 656 case Constant: 657 return MCSymbol::AbsolutePseudoSection; 658 659 case SymbolRef: { 660 const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); 661 const MCSymbol &Sym = SRE->getSymbol(); 662 663 if (Sym.isDefined()) 664 return &Sym.getSection(); 665 666 return 0; 667 } 668 669 case Unary: 670 return cast<MCUnaryExpr>(this)->getSubExpr()->FindAssociatedSection(); 671 672 case Binary: { 673 const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); 674 const MCSection *LHS_S = BE->getLHS()->FindAssociatedSection(); 675 const MCSection *RHS_S = BE->getRHS()->FindAssociatedSection(); 676 677 // If either section is absolute, return the other. 678 if (LHS_S == MCSymbol::AbsolutePseudoSection) 679 return RHS_S; 680 if (RHS_S == MCSymbol::AbsolutePseudoSection) 681 return LHS_S; 682 683 // Otherwise, return the first non-null section. 684 return LHS_S ? LHS_S : RHS_S; 685 } 686 } 687 688 llvm_unreachable("Invalid assembly expression kind!"); 689} 690