LLVM: lib/MC/MCExpr.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

12#include "llvm/Config/llvm-config.h"

26#include

27#include

28

29using namespace llvm;

30

31#define DEBUG_TYPE "mcexpr"

32

33namespace {

35

36STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");

37

38}

39}

40

42 switch (Op) {

45 return 1;

46 default:

47 return 0;

48 }

49}

50

51

52

53

55 int SurroundingPrec) const {

56 constexpr int MaxPrec = 9;

65 PrintInHex = true;

66 if (PrintInHex)

67 switch (SizeInBytes) {

68 default:

70 break;

71 case 1:

73 break;

74 case 2:

76 break;

77 case 4:

79 break;

80 case 8:

82 break;

83 }

84 else

86 return;

87 }

91 Sym.print(OS, MAI);

92

94 if (Kind) {

95 if (!MAI)

96 OS << "@<variant " << Kind << '>';

99 else

101 }

102

103 return;

104 }

105

113 }

114 UE.getSubExpr()->print(OS, MAI, MaxPrec);

115 return;

116 }

117

120

121

122

123

124

125

127 bool Paren = Prec < SurroundingPrec;

128 if (Paren)

129 OS << '(';

130

131

132 int SubPrec = Prec ? Prec : MaxPrec;

133 BE.getLHS()->print(OS, MAI, SubPrec);

134

137

139 if (RHSC->getValue() < 0) {

140 OS << RHSC->getValue();

141 if (Paren)

142 OS << ')';

143 return;

144 }

145 }

146

147 OS << '+';

148 break;

168 }

169

170 BE.getRHS()->print(OS, MAI, SubPrec + 1);

171 if (Paren)

172 OS << ')';

173 return;

174 }

175

178 if (MAI)

180

181

182 OS << "specifier(" << SE.getSpecifier() << ',';

183 SE.getSubExpr()->print(OS, nullptr);

184 OS << ')';

185 return;

186 }

187 }

188

190}

191

192#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

194 print(dbgs(), nullptr);

195 dbgs() << '\n';

196}

197#endif

198

199

200

204 return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc);

205}

206

209 return new (Ctx) MCUnaryExpr(Opc, Expr, Loc);

210}

211

213 bool PrintInHex,

214 unsigned SizeInBytes) {

215 return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes);

216}

217

218

219

220MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, Spec specifier,

222 : MCExpr(MCExpr::SymbolRef, Loc, specifier), Symbol(Symbol) {

224}

225

229 return new (Ctx) MCSymbolRefExpr(Sym, specifier, Ctx.getAsmInfo(), Loc);

230}

231

232

233

234void MCTargetExpr::anchor() {}

235

236

237

238bool MCExpr::evaluateAsAbsolute(int64_t &Res) const {

239 return evaluateAsAbsolute(Res, nullptr, false);

240}

241

242bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {

243 return evaluateAsAbsolute(Res, &Asm, false);

244}

245

246bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {

247 return evaluateAsAbsolute(Res, Asm, false);

248}

249

251 return evaluateAsAbsolute(Res, &Asm, true);

252}

253

254bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm,

255 bool InSet) const {

257

258

260 Res = CE->getValue();

261 return true;

262 }

263

265 Res = Value.getConstant();

266

267

268

269 return IsRelocatable && Value.isAbsolute() && Value.getSpecifier() == 0;

270}

271

272

276 int64_t &Addend) {

277 if (A || B)

278 return;

279

281 if (SA.isUndefined() || SB.isUndefined())

282 return;

283 if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(SA, SB, InSet))

284 return;

285

286 auto FinalizeFolding = [&]() {

287

288

289 if (Asm->isThumbFunc(&SA))

290 Addend |= 1;

291

292

293

294 A = B = nullptr;

295 };

296

298 const MCFragment *FB = SB.getFragment();

301 if (&SecA != &SecB)

302 return;

303

304

305

306

307

308

309

310 bool Layout = Asm->hasLayout();

312

313

314 if (FA == FB && !SA.isVariable() && !SB.isVariable()) {

315 Addend += SA.getOffset() - SB.getOffset();

316 return FinalizeFolding();

317 }

318

319

320 Addend += Asm->getSymbolOffset(SA) - Asm->getSymbolOffset(SB);

321 FinalizeFolding();

322 } else {

323

324

325

326

327

328

329

330 if (SA.isVariable() || SB.isVariable())

331 return;

332

333

334

336 if (FA == FB)

338 else

340

342 int64_t Displacement = SA.getOffset() - SB.getOffset();

346 Displacement *= -1;

347 }

348

349

350

351

352

353 bool BBeforeRelax = false, AAfterRelax = false;

354 for (auto F = FB; F; F = F->getNext()) {

355 if (F && F->isLinkerRelaxable()) {

356 if (&*F != FB || SBOffset != F->getSize())

357 BBeforeRelax = true;

358 if (&*F != FA || SAOffset == F->getSize())

359 AAfterRelax = true;

360 if (BBeforeRelax && AAfterRelax)

361 return;

362 }

363 if (&*F == FA) {

364

365

366 Addend += Reverse ? -Displacement : Displacement;

367 FinalizeFolding();

368 return;

369 }

370

371 int64_t Num;

373 Displacement += F->getFixedSize();

376 Asm->hasFinalLayout()) {

377

378

379

380 Displacement += F->getSize();

382 FF && FF->getNumValues().evaluateAsAbsolute(Num)) {

383 Displacement += Num * FF->getValueSize();

384 } else {

385 return;

386 }

387 }

388 }

389}

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

410 const MCSymbol *LHS_A = LHS.getAddSym();

411 const MCSymbol *LHS_B = LHS.getSubSym();

412 int64_t LHS_Cst = LHS.getConstant();

413

414 const MCSymbol *RHS_A = RHS.getAddSym();

415 const MCSymbol *RHS_B = RHS.getSubSym();

416 int64_t RHS_Cst = RHS.getConstant();

417

418

419 int64_t Result_Cst = LHS_Cst + RHS_Cst;

420

421

422 if (Asm && !LHS.getSpecifier() && !RHS.getSpecifier()) {

423

424

425

426

427 if (LHS_A && RHS_B) {

429 }

430 if (RHS_A && LHS_B) {

432 }

433 }

434

435

436 if ((LHS_A && RHS_A) || (LHS_B && RHS_B))

437 return false;

438

439

440

441 auto *A = LHS_A ? LHS_A : RHS_A;

442 auto *B = LHS_B ? LHS_B : RHS_B;

443 auto Spec = LHS.getSpecifier();

445 Spec = RHS.getSpecifier();

447 return true;

448}

449

456

458 bool InSet) const {

459 ++stats::MCExprEvaluate;

462 return cast(this)->evaluateAsRelocatableImpl(Res, Asm);

465 return true;

466

470 const auto Kind = SRE->getKind();

471 bool Layout = Asm && Asm->hasLayout();

472

473

474

475

476

478 if (Asm && Asm->hasFinalLayout()) {

479 Asm->getContext().reportError(

481 "cyclic dependency detected for symbol '" + Sym.getName() + "'");

483 }

484 return false;

485 }

489 bool IsMachO =

490 Asm && Asm->getContext().getAsmInfo()->hasSubsectionsViaSymbols();

492 InSet || IsMachO))

493 return false;

494

495

496

499 if (InSet || !(A && B && A->isInSection())) {

500 if (Kind) {

503 return true;

504 }

505

506

507

510 return false;

511 Res.Specifier = Kind;

512 }

513 if (!IsMachO)

514 return true;

515

516

517

518

519

520

521

522

523 if (A && B)

524 return true;

525

527 return true;

528 }

529 }

530

532 return true;

533 }

534

538

540 return false;

543 if (Value.isAbsolute())

544 return false;

546 break;

548

549 if (Value.getAddSym() && Value.getSubSym())

550 return false;

551

552

555 break;

557 if (Value.isAbsolute())

558 return false;

560 break;

563 break;

564 }

565

566 return true;

567 }

568

571 MCValue LHSValue, RHSValue;

572

575

580 Res = MCValue::get(L->isEqualTo(R) ? -1 : 0);

581 return true;

583 Res = MCValue::get(L->isEqualTo(R) ? 0 : -1);

584 return true;

585 default:

586 break;

587 }

588 }

589 }

590 return false;

591 }

592

593

594

598 switch (Op) {

599 default:

600 return false;

604 std::swap(RHSValue.SymA, RHSValue.SymB);

605 RHSValue.Cst = -(uint64_t)RHSValue.Cst;

606 }

608 LHSValue.Cst += RHSValue.Cst;

609 Res = LHSValue;

610 return true;

611 }

613 RHSValue.Cst += LHSValue.Cst;

614 Res = RHSValue;

615 return true;

616 }

617 if (LHSValue.SymB && LHSValue.Specifier)

618 return false;

619 if (RHSValue.SymB && RHSValue.Specifier)

620 return false;

622 }

623 }

624

625

626

627

628 int64_t Result = 0;

629 switch (Op) {

635

636

637

638

639

640

641 if (RHS == 0)

642 return false;

644 Result = LHS / RHS;

645 else

646 Result = LHS % RHS;

647 break;

663 }

664

665 switch (Op) {

666 default:

668 break;

675

677 break;

678 }

679

680 return true;

681 }

683

684

685 return Asm && Asm->getContext().getAsmInfo()->evaluateAsRelocatableImpl(

687 }

688

690}

691

695

697

700

702 auto &Sym =

711 return F;

712 }

713

715 return cast(this)->getSubExpr()->findAssociatedFragment();

716

721

722

724 return RHS_F;

726 return LHS_F;

727

728

731

732

733 return LHS_F ? LHS_F : RHS_F;

734 }

735

738 }

739

741}

742

747

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

static void attemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, bool InSet, const MCSymbol *&A, const MCSymbol *&B, int64_t &Addend)

Helper method for.

Definition MCExpr.cpp:273

static int getPrecedence(MCBinaryExpr::Opcode Op)

Definition MCExpr.cpp:41

This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

This class is intended to be used as a base class for asm properties and features specific to the tar...

virtual void printSpecifierExpr(raw_ostream &, const MCSpecifierExpr &) const

StringRef getSpecifierName(uint32_t S) const

bool useParensForSpecifier() const

Binary assembler expressions.

const MCExpr * getLHS() const

Get the left-hand side expression of the binary operator.

const MCExpr * getRHS() const

Get the right-hand side expression of the binary operator.

Opcode getOpcode() const

Get the kind of this binary expression.

static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

Definition MCExpr.cpp:201

@ AShr

Arithmetic shift right.

@ LShr

Logical shift right.

@ GTE

Signed greater than or equal comparison (result is either 0 or some target-specific non-zero value).

@ GT

Signed greater than comparison (result is either 0 or some target-specific non-zero value)

@ Xor

Bitwise exclusive or.

@ LT

Signed less than comparison (result is either 0 or some target-specific non-zero value).

@ LTE

Signed less than or equal comparison (result is either 0 or some target-specific non-zero value).

@ NE

Inequality comparison.

static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Definition MCExpr.cpp:212

Context object for machine code objects.

Base class for the full range of assembler expressions which are needed for parsing.

LLVM_ABI bool evaluateAsValue(MCValue &Res, const MCAssembler &Asm) const

Try to evaluate the expression to the form (a - b + constant) where neither a nor b are variables.

Definition MCExpr.cpp:453

LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const

Try to evaluate the expression to a relocatable value, i.e.

Definition MCExpr.cpp:450

MCExpr(ExprKind Kind, SMLoc Loc, unsigned SubclassData=0)

@ Unary

Unary expressions.

@ Constant

Constant expressions.

@ SymbolRef

References to labels and assigned expressions.

@ Target

Target specific expression.

@ Specifier

Expression with a relocation specifier.

@ Binary

Binary expressions.

static LLVM_ABI bool evaluateSymbolicAdd(const MCAssembler *, bool, const MCValue &, const MCValue &, MCValue &)

Definition MCExpr.cpp:407

LLVM_ABI bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const

Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.

Definition MCExpr.cpp:250

LLVM_ABI MCFragment * findAssociatedFragment() const

Find the "associated section" for this expression, which is currently defined as the absolute section...

Definition MCExpr.cpp:692

LLVM_ABI bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, bool InSet) const

Definition MCExpr.cpp:457

LLVM_ABI void dump() const

Definition MCExpr.cpp:193

unsigned getLayoutOrder() const

MCSection * getParent() const

Instances of this class represent a uniqued identifier for a section in the current translation unit.

bool isLinkerRelaxable() const

static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())

Definition MCExpr.cpp:743

MCSpecifierExpr(const MCExpr *Expr, Spec S, SMLoc Loc=SMLoc())

Represent a reference to a symbol from inside an expression.

const MCSymbol & getSymbol() const

VariantKind getKind() const

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const

print - Print the value to the stream OS.

void setIsResolving(bool V)

bool isUndefined() const

isUndefined - Check if this symbol undefined (i.e., implicitly defined).

StringRef getName() const

getName - Get the symbol name.

bool isWeakExternal() const

bool isVariable() const

isVariable - Check if this is a variable symbol.

LLVM_ABI void setVariableValue(const MCExpr *Value)

MCFragment * Fragment

If a symbol has a Fragment, the section is implied, so we only need one pointer.

static LLVM_ABI MCFragment * AbsolutePseudoFragment

const MCExpr * getVariableValue() const

Get the expression of the variable symbol.

MCFragment * getFragment() const

uint64_t getOffset() const

Extension point for target-specific MCExpr subclasses to implement.

Unary assembler expressions.

Opcode getOpcode() const

Get the kind of this unary expression.

static LLVM_ABI const MCUnaryExpr * create(Opcode Op, const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())

Definition MCExpr.cpp:207

const MCExpr * getSubExpr() const

Get the child of this unary expression.

static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)

const MCSymbol * getAddSym() const

int64_t getConstant() const

uint32_t getSpecifier() const

const MCSymbol * getSubSym() const

bool isAbsolute() const

Is this an absolute (as opposed to relocatable) value.

Represents a location in source code.

static Twine utohexstr(uint64_t Val)

LLVM Value Representation.

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

format_object< Ts... > format(const char *Fmt, const Ts &... Vals)

These are helper functions used to produce formatted output.

DWARFExpression::Operation Op

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.