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