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