LLVM: lib/Target/PowerPC/PPCAsmPrinter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

78#include

79#include

80#include

81#include

82

83using namespace llvm;

85

86#define DEBUG_TYPE "asmprinter"

87

88STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted.");

89STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries.");

91 "Number of Internal Linkage Global TOC Entries.");

93 "Number of External Linkage Global TOC Entries.");

94STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries.");

95STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries.");

96STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries.");

97STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries.");

98

100 "aix-ssp-tb-bit", cl::init(false),

101 cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden);

102

103

104

105

106

107namespace llvm {

108template <>

109struct DenseMapInfo<std::pair<const MCSymbol *, PPCMCExpr::Specifier>> {

110 using TOCKey = std::pair<const MCSymbol *, PPCMCExpr::Specifier>;

111

122};

123}

124

125namespace {

126

127enum {

128

129 Tag_GNU_Power_ABI_FP = 4,

130 Tag_GNU_Power_ABI_Vector = 8,

131 Tag_GNU_Power_ABI_Struct_Return = 12,

132

133

134 Val_GNU_Power_ABI_NoFloat = 0b00,

135 Val_GNU_Power_ABI_HardFloat_DP = 0b01,

136 Val_GNU_Power_ABI_SoftFloat_DP = 0b10,

137 Val_GNU_Power_ABI_HardFloat_SP = 0b11,

138

139 Val_GNU_Power_ABI_LDBL_IBM128 = 0b0100,

140 Val_GNU_Power_ABI_LDBL_64 = 0b1000,

141 Val_GNU_Power_ABI_LDBL_IEEE128 = 0b1100,

142};

143

144class PPCAsmPrinter : public AsmPrinter {

145protected:

146

147

148

149

150

151

152

153 MapVector<std::pair<const MCSymbol *, PPCMCExpr::Specifier>, MCSymbol *> TOC;

154 const PPCSubtarget *Subtarget = nullptr;

155

156

157

158

159 MapVector<const GlobalValue *, uint64_t> TLSVarsToAddressMapping;

160

161public:

162 explicit PPCAsmPrinter(TargetMachine &TM,

163 std::unique_ptr Streamer, char &ID)

164 : AsmPrinter(TM, std::move(Streamer), ID) {}

165

166 StringRef getPassName() const override { return "PowerPC Assembly Printer"; }

167

168 enum TOCEntryType {

169 TOCType_ConstantPool,

170 TOCType_GlobalExternal,

171 TOCType_GlobalInternal,

172 TOCType_JumpTable,

173 TOCType_ThreadLocal,

174 TOCType_BlockAddress,

175 TOCType_EHBlock

176 };

177

178 MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,

180

181 bool doInitialization(Module &M) override {

182 if (!TOC.empty())

183 TOC.clear();

185 }

186

187 const MCExpr *symbolWithSpecifier(const MCSymbol *S,

190

191

192

193

194 void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);

195

196 void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;

197 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

198 const char *ExtraCode, raw_ostream &O) override;

199 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,

200 const char *ExtraCode, raw_ostream &O) override;

201

202 void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI);

203 void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI);

205 void EmitAIXTlsCallHelper(const MachineInstr *MI);

206 const MCExpr *getAdjustedFasterLocalExpr(const MachineOperand &MO,

208 bool runOnMachineFunction(MachineFunction &MF) override {

209 Subtarget = &MF.getSubtarget();

211 emitXRayTable();

213 }

214};

215

216

217class PPCLinuxAsmPrinter : public PPCAsmPrinter {

218public:

219 static char ID;

220

221 explicit PPCLinuxAsmPrinter(TargetMachine &TM,

222 std::unique_ptr Streamer)

223 : PPCAsmPrinter(TM, std::move(Streamer), ID) {}

224

225 StringRef getPassName() const override {

226 return "Linux PPC Assembly Printer";

227 }

228

229 void emitGNUAttributes(Module &M);

230

231 void emitStartOfAsmFile(Module &M) override;

232 void emitEndOfAsmFile(Module &) override;

233

234 void emitFunctionEntryLabel() override;

235

236 void emitFunctionBodyStart() override;

237 void emitFunctionBodyEnd() override;

239};

240

241class PPCAIXAsmPrinter : public PPCAsmPrinter {

242private:

243

244

245 SmallSetVector<MCSymbol *, 8> ExtSymSDNodeSymbols;

246

247

248

249 std::string FormatIndicatorAndUniqueModId;

250

251

252

253 DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>

254 GOAliasMap;

255

256 uint16_t getNumberOfVRSaved();

257 void emitTracebackTable();

258

260

261 void emitGlobalVariableHelper(const GlobalVariable *);

262

263

264 uint64_t getAliasOffset(const Constant *C);

265

266public:

267 static char ID;

268

269 PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer)

270 : PPCAsmPrinter(TM, std::move(Streamer), ID) {

271 if (MAI->isLittleEndian())

273 "cannot create AIX PPC Assembly Printer for a little-endian target");

274 }

275

276 StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }

277

278 bool doInitialization(Module &M) override;

279

280 void emitXXStructorList(const DataLayout &DL, const Constant *List,

281 bool IsCtor) override;

282

283 void SetupMachineFunction(MachineFunction &MF) override;

284

285 void emitGlobalVariable(const GlobalVariable *GV) override;

286

287 void emitFunctionDescriptor() override;

288

289 void emitFunctionEntryLabel() override;

290

291 void emitFunctionBodyEnd() override;

292

293 void emitPGORefs(Module &M);

294

295 void emitGCOVRefs();

296

297 void emitEndOfAsmFile(Module &) override;

298

299 void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;

300

302

303 bool doFinalization(Module &M) override;

304

305 void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override;

306

307 void emitModuleCommandLines(Module &M) override;

308};

309

310}

311

312void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,

314

315 const GlobalValue *GV = MO.getGlobal();

316 getSymbol(GV)->print(O, MAI);

318}

319

320void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,

321 raw_ostream &O) {

322 const DataLayout &DL = getDataLayout();

323 const MachineOperand &MO = MI->getOperand(OpNo);

324

327

329

330

331

333 return;

334 }

337 return;

338

341 return;

343 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'

345 return;

347 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);

348 return;

350 PrintSymbolOperand(MO, O);

351 return;

352 }

353

354 default:

355 O << "<unknown operand type: " << (unsigned)MO.getType() << ">";

356 return;

357 }

358}

359

360

361

362bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

363 const char *ExtraCode, raw_ostream &O) {

364

365 if (ExtraCode && ExtraCode[0]) {

366 if (ExtraCode[1] != 0) return true;

367

368 switch (ExtraCode[0]) {

369 default:

370

372 case 'L':

373

374 if (MI->getOperand(OpNo).isReg() ||

375 OpNo+1 == MI->getNumOperands() ||

376 MI->getOperand(OpNo+1).isReg())

377 return true;

378 ++OpNo;

379 break;

380 case 'I':

381

382

383 if (MI->getOperand(OpNo).isImm())

384 O << "i";

385 return false;

386 case 'x':

387 if(MI->getOperand(OpNo).isReg())

388 return true;

389

390

393 Reg = PPC::VSX32 + (Reg - PPC::V0);

395 Reg = PPC::VSX32 + (Reg - PPC::VF0);

400 return false;

401 }

402 }

403

405 return false;

406}

407

408

409

410

411bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,

412 const char *ExtraCode,

413 raw_ostream &O) {

414 if (ExtraCode && ExtraCode[0]) {

415 if (ExtraCode[1] != 0) return true;

416

417 switch (ExtraCode[0]) {

418 default: return true;

419 case 'L':

420 O << getDataLayout().getPointerSize() << "(";

422 O << ")";

423 return false;

424 case 'y':

425 O << "0, ";

427 return false;

428 case 'I':

429

430

431 if (MI->getOperand(OpNo).isImm())

432 O << "i";

433 return false;

434 case 'U':

435 case 'X':

436

437

438

439

440

441

442 assert(MI->getOperand(OpNo).isReg());

443 return false;

444 }

445 }

446

447 assert(MI->getOperand(OpNo).isReg());

448 O << "0(";

450 O << ")";

451 return false;

452}

453

455 ++NumTOCEntries;

456 switch (Type) {

457 case PPCAsmPrinter::TOCType_ConstantPool:

458 ++NumTOCConstPool;

459 break;

460 case PPCAsmPrinter::TOCType_GlobalInternal:

461 ++NumTOCGlobalInternal;

462 break;

463 case PPCAsmPrinter::TOCType_GlobalExternal:

464 ++NumTOCGlobalExternal;

465 break;

466 case PPCAsmPrinter::TOCType_JumpTable:

467 ++NumTOCJumpTable;

468 break;

469 case PPCAsmPrinter::TOCType_ThreadLocal:

470 ++NumTOCThreadLocal;

471 break;

472 case PPCAsmPrinter::TOCType_BlockAddress:

473 ++NumTOCBlockAddress;

474 break;

475 case PPCAsmPrinter::TOCType_EHBlock:

476 ++NumTOCEHBlock;

477 break;

478 }

479}

480

485

486

487

489 return ModuleModel;

490

492 assert(GV && "expected global for MO_GlobalAddress");

493

495}

496

498 switch (CM) {

501 return;

504 return;

505 default:

507 }

508}

509

510

511

512

513MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,

514 TOCEntryType Type,

516

517 auto [It, Inserted] = TOC.try_emplace({Sym, Spec});

518 if (Inserted)

520

521 MCSymbol *&TOCEntry = It->second;

522 if (!TOCEntry)

523 TOCEntry = createTempSymbol("C");

524 return TOCEntry;

525}

526

527void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) {

528 unsigned NumNOPBytes = MI.getOperand(1).getImm();

529

530 auto &Ctx = OutStreamer->getContext();

531 MCSymbol *MILabel = Ctx.createTempSymbol();

532 OutStreamer->emitLabel(MILabel);

533

535 assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");

536

537

538 const MachineBasicBlock &MBB = *MI.getParent();

540 ++MII;

541 while (NumNOPBytes > 0) {

542 if (MII == MBB.end() || MII->isCall() ||

543 MII->getOpcode() == PPC::DBG_VALUE ||

544 MII->getOpcode() == TargetOpcode::PATCHPOINT ||

545 MII->getOpcode() == TargetOpcode::STACKMAP)

546 break;

547 ++MII;

548 NumNOPBytes -= 4;

549 }

550

551

552 for (unsigned i = 0; i < NumNOPBytes; i += 4)

553 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));

554}

555

556

557

558void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {

559 auto &Ctx = OutStreamer->getContext();

560 MCSymbol *MILabel = Ctx.createTempSymbol();

561 OutStreamer->emitLabel(MILabel);

562

564 PatchPointOpers Opers(&MI);

565

566 unsigned EncodedBytes = 0;

567 const MachineOperand &CalleeMO = Opers.getCallTarget();

568

569 if (CalleeMO.isImm()) {

570 int64_t CallTarget = CalleeMO.getImm();

571 if (CallTarget) {

572 assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&

573 "High 16 bits of call target should be zero.");

574 Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();

575 EncodedBytes = 0;

576

577 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)

578 .addReg(ScratchReg)

579 .addImm((CallTarget >> 32) & 0xFFFF));

580 ++EncodedBytes;

581 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC)

582 .addReg(ScratchReg)

583 .addReg(ScratchReg)

584 .addImm(32).addImm(16));

585 ++EncodedBytes;

586 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8)

587 .addReg(ScratchReg)

588 .addReg(ScratchReg)

589 .addImm((CallTarget >> 16) & 0xFFFF));

590 ++EncodedBytes;

591 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8)

592 .addReg(ScratchReg)

593 .addReg(ScratchReg)

594 .addImm(CallTarget & 0xFFFF));

595

596

598 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD)

599 .addReg(PPC::X2)

600 .addImm(TOCSaveOffset)

601 .addReg(PPC::X1));

602 ++EncodedBytes;

603

604

605

607

608

609

610 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)

611 .addReg(PPC::X2)

612 .addImm(8)

613 .addReg(ScratchReg));

614 ++EncodedBytes;

615 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)

616 .addReg(ScratchReg)

617 .addImm(0)

618 .addReg(ScratchReg));

619 ++EncodedBytes;

620 }

621

622 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8)

623 .addReg(ScratchReg));

624 ++EncodedBytes;

625 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8));

626 ++EncodedBytes;

627

628

629 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)

630 .addReg(PPC::X2)

631 .addImm(TOCSaveOffset)

632 .addReg(PPC::X1));

633 ++EncodedBytes;

634 }

635 } else if (CalleeMO.isGlobal()) {

636 const GlobalValue *GValue = CalleeMO.getGlobal();

637 MCSymbol *MOSymbol = getSymbol(GValue);

639

640 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP)

641 .addExpr(SymVar));

642 EncodedBytes += 2;

643 }

644

645

646 EncodedBytes *= 4;

647

648

649 unsigned NumBytes = Opers.getNumPatchBytes();

650 assert(NumBytes >= EncodedBytes &&

651 "Patchpoint can't request size less than the length of a call.");

652 assert((NumBytes - EncodedBytes) % 4 == 0 &&

653 "Invalid number of NOP bytes requested!");

654 for (unsigned i = EncodedBytes; i < NumBytes; i += 4)

655 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));

656}

657

658

659

660

663 switch (MIOpc) {

664 default:

665 SymName = ".__tls_get_addr";

666 break;

667 case PPC::GETtlsTpointer32AIX:

668 SymName = ".__get_tpointer";

669 break;

670 case PPC::GETtlsMOD32AIX:

671 case PPC::GETtlsMOD64AIX:

672 SymName = ".__tls_get_mod";

673 break;

674 }

675 return Ctx

678 ->getQualNameSymbol();

679}

680

681void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) {

683 "Only expecting to emit calls to get the thread pointer on AIX!");

684

687 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef));

688}

689

690

691

692void PPCAsmPrinter::emitTlsCall(const MachineInstr *MI,

695 unsigned Opcode = PPC::BL8_NOP_TLS;

696

697 assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI");

701 Opcode = PPC::BL8_NOTOC_TLS;

702 }

703 const Module *M = MF->getFunction().getParent();

704

705 assert(MI->getOperand(0).isReg() &&

706 ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||

707 (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&

708 "GETtls[ld]ADDR[32] must define GPR3");

709 assert(MI->getOperand(1).isReg() &&

710 ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||

711 (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&

712 "GETtls[ld]ADDR[32] must read GPR3");

713

715

716

717

718

719 Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;

720 (void)VarOffsetReg;

721 assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||

722 MI->getOpcode() == PPC::GETtlsMOD64AIX ||

723 (MI->getOperand(2).isReg() &&

724 MI->getOperand(2).getReg() == VarOffsetReg)) &&

725 "GETtls[ld]ADDR[32] must read GPR4");

726 EmitAIXTlsCallHelper(MI);

727 return;

728 }

729

730 MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol("__tls_get_addr");

731

732 if (Subtarget->is32BitELFABI() && isPositionIndependent())

734

736

737

738 if (Kind == PPC::S_PLT && Subtarget->isSecurePlt() &&

742 const MachineOperand &MO = MI->getOperand(2);

743 const GlobalValue *GValue = MO.getGlobal();

744 MCSymbol *MOSymbol = getSymbol(GValue);

746 EmitToStreamer(*OutStreamer,

747 MCInstBuilder(Subtarget->isPPC64() ? Opcode

748 : (unsigned)PPC::BL_TLS)

749 .addExpr(TlsRef)

750 .addExpr(SymVar));

751}

752

753

754

770

771static PPCAsmPrinter::TOCEntryType

773

774

776 return PPCAsmPrinter::TOCType_ThreadLocal;

777

785 return PPCAsmPrinter::TOCType_GlobalExternal;

786

787 return PPCAsmPrinter::TOCType_GlobalInternal;

788 }

790 return PPCAsmPrinter::TOCType_ConstantPool;

792 return PPCAsmPrinter::TOCType_JumpTable;

794 return PPCAsmPrinter::TOCType_BlockAddress;

795 default:

796 llvm_unreachable("Unexpected operand type to get TOC type.");

797 }

798}

799

800const MCExpr *PPCAsmPrinter::symbolWithSpecifier(const MCSymbol *S,

803}

804

805

806

807

808void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {

809 PPC_MC::verifyInstructionPredicates(MI->getOpcode(),

810 getSubtargetInfo().getFeatureBits());

811

812 MCInst TmpInst;

813 const bool IsPPC64 = Subtarget->isPPC64();

814 const bool IsAIX = Subtarget->isAIXABI();

815 const bool HasAIXSmallLocalTLS = Subtarget->hasAIXSmallLocalExecTLS() ||

816 Subtarget->hasAIXSmallLocalDynamicTLS();

817 const Module *M = MF->getFunction().getParent();

819

820#ifndef NDEBUG

821

822 if (MI->isInlineAsm()) {

823 for (const MachineOperand &MO: MI->operands()) {

824 if (MO.isReg()) {

826 if (Subtarget->hasSPE()) {

833 )

835 } else {

837 llvm_unreachable("SPE register found in FPU-targeted code!");

838 }

839 }

840 }

841 }

842#endif

843

844 auto getTOCRelocAdjustedExprForXCOFF = [this](const MCExpr *Expr,

845 ptrdiff_t OriginalOffset) {

846

847

848

849

850

851

852 ptrdiff_t Adjustment =

856 };

857

858 auto getTOCEntryLoadingExprForXCOFF =

859 [IsPPC64, getTOCRelocAdjustedExprForXCOFF,

860 this](const MCSymbol *MOSymbol, const MCExpr *Expr,

862 const unsigned EntryByteSize = IsPPC64 ? 8 : 4;

863 const auto TOCEntryIter = TOC.find({MOSymbol, VK});

864 assert(TOCEntryIter != TOC.end() &&

865 "Could not find the TOC entry for this symbol.");

866 const ptrdiff_t EntryDistanceFromTOCBase =

867 (TOCEntryIter - TOC.begin()) * EntryByteSize;

868 constexpr int16_t PositiveTOCRange = INT16_MAX;

869

870 if (EntryDistanceFromTOCBase > PositiveTOCRange)

871 return getTOCRelocAdjustedExprForXCOFF(Expr, EntryDistanceFromTOCBase);

872

873 return Expr;

874 };

875 auto getSpecifier = [&](const MachineOperand &MO) {

876

877

878

883 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");

889

890

891 PPCFunctionInfo *FuncInfo = MF->getInfo();

895 dbgs() << "Current function uses IE access for default LD vars.\n");

897 }

898 llvm_unreachable("Only expecting local-exec or initial-exec accesses!");

899 }

900

901

902

907

908

909

915 };

916

917

918 switch (MI->getOpcode()) {

919 default: break;

920 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {

922 "AIX does not support patchable function entry!");

923 const Function &F = MF->getFunction();

924 unsigned Num = 0;

925 (void)F.getFnAttribute("patchable-function-entry")

926 .getValueAsString()

927 .getAsInteger(10, Num);

928 if (!Num)

929 return;

930 emitNops(Num);

931 return;

932 }

933 case TargetOpcode::DBG_VALUE:

935 case TargetOpcode::STACKMAP:

936 return LowerSTACKMAP(SM, *MI);

937 case TargetOpcode::PATCHPOINT:

938 return LowerPATCHPOINT(SM, *MI);

939

940 case PPC::MoveGOTtoLR: {

941

942

943

944

945

946

948 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));

952

953

954 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));

955 return;

956 }

957 case PPC::MovePCtoLR:

958 case PPC::MovePCtoLR8: {

959

960

961

962

963 MCSymbol *PICBase = MF->getPICBaseSymbol();

964

965

966 EmitToStreamer(*OutStreamer,

967 MCInstBuilder(PPC::BCLalways)

968

969

971

972

973 OutStreamer->emitLabel(PICBase);

974 return;

975 }

976 case PPC::UpdateGBR: {

977

978

979

980

981

982

983

985 if (Subtarget->isSecurePlt() && isPositionIndependent() ) {

987 MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(

989 : ".LTOC");

990 const MCExpr *PB =

992

995

996 const MCExpr *DeltaHi =

998 EmitToStreamer(

999 *OutStreamer,

1000 MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi));

1001

1002 const MCExpr *DeltaLo =

1004 EmitToStreamer(

1005 *OutStreamer,

1006 MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo));

1007 return;

1008 } else {

1010 MF->getInfo()->getPICOffsetSymbol(*MF);

1013 const MCExpr *PB =

1015 OutContext);

1016 const MCOperand TR = TmpInst.getOperand(1);

1017 const MCOperand PICR = TmpInst.getOperand(0);

1018

1019

1024 EmitToStreamer(*OutStreamer, TmpInst);

1025

1030 EmitToStreamer(*OutStreamer, TmpInst);

1031 return;

1032 }

1033 }

1034 case PPC::LWZtoc: {

1035

1037

1038

1040

1041 const MachineOperand &MO = MI->getOperand(1);

1043 "Invalid operand for LWZtoc.");

1044

1045

1047

1048

1049

1051 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_GOT);

1053 EmitToStreamer(*OutStreamer, TmpInst);

1054 return;

1055 }

1056

1058

1059

1060

1061

1065

1066

1067

1068

1069 if (IsAIX) {

1072 "This pseudo should only be selected for 32-bit small code model.");

1073 Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK);

1075

1076

1077 if (isVerbose())

1078 OutStreamer->getCommentOS() << MO << '\n';

1079 EmitToStreamer(*OutStreamer, TmpInst);

1080 return;

1081 }

1082

1083

1084

1086 OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext);

1089 EmitToStreamer(*OutStreamer, TmpInst);

1090 return;

1091 }

1092 case PPC::ADDItoc:

1093 case PPC::ADDItoc8: {

1095 "PseudoOp only valid for small code model AIX");

1096

1097

1099

1100

1101 TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));

1102

1103 const MachineOperand &MO = MI->getOperand(2);

1104 assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");

1105

1106

1108

1110

1112 EmitToStreamer(*OutStreamer, TmpInst);

1113 return;

1114 }

1115 case PPC::LDtocJTI:

1116 case PPC::LDtocCPT:

1117 case PPC::LDtocBA:

1118 case PPC::LDtoc: {

1119

1121

1122

1124

1125 const MachineOperand &MO = MI->getOperand(1);

1127 "Invalid operand!");

1128

1129

1131

1133

1134

1135

1136

1139

1141 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, VKExpr);

1143 IsAIX ? getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK) : Exp);

1144

1145

1146 if (isVerbose() && IsAIX)

1147 OutStreamer->getCommentOS() << MO << '\n';

1148 EmitToStreamer(*OutStreamer, TmpInst);

1149 return;

1150 }

1151 case PPC::ADDIStocHA: {

1152 const MachineOperand &MO = MI->getOperand(2);

1153

1155 "Invalid operand for ADDIStocHA.");

1156 assert((IsAIX && !IsPPC64 &&

1158 "This pseudo should only be selected for 32-bit large code model on"

1159 " AIX.");

1160

1161

1163

1164

1166

1167

1169

1171

1172

1173

1174

1175

1176

1177

1178 if (![](const MachineOperand &MO) {

1180 return false;

1181

1183 if (!GV)

1184 return false;

1186 }(MO)) {

1188 }

1189

1190 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, PPC::S_U);

1192 EmitToStreamer(*OutStreamer, TmpInst);

1193 return;

1194 }

1195 case PPC::LWZtocL: {

1196 const MachineOperand &MO = MI->getOperand(1);

1197

1199 "Invalid operand for LWZtocL.");

1200 assert(IsAIX && !IsPPC64 &&

1202 "This pseudo should only be selected for 32-bit large code model on"

1203 " AIX.");

1204

1205

1207

1208

1210

1211

1213

1215

1216

1217

1218

1219

1222 const MCExpr *Exp = symbolWithSpecifier(TOCEntry, PPC::S_L);

1224 EmitToStreamer(*OutStreamer, TmpInst);

1225 return;

1226 }

1227 case PPC::ADDIStocHA8: {

1228

1230

1231

1232

1233

1234

1236

1237 const MachineOperand &MO = MI->getOperand(2);

1239 "Invalid operand for ADDIStocHA8!");

1240

1242

1244

1245 const bool GlobalToc =

1247

1250

1254

1256

1257 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);

1258

1262 OutContext),

1263 OutContext);

1264

1266 EmitToStreamer(*OutStreamer, TmpInst);

1267 return;

1268 }

1269 case PPC::LDtocL: {

1270

1272

1273

1274

1275

1276

1278

1279 const MachineOperand &MO = MI->getOperand(1);

1282 "Invalid operand for LDtocL!");

1283

1286 "LDtocL used on symbol that could be accessed directly is "

1287 "invalid. Must match ADDIStocHA8."));

1288

1290

1296

1298 const MCExpr *Exp = symbolWithSpecifier(MOSymbol, VK);

1300 EmitToStreamer(*OutStreamer, TmpInst);

1301 return;

1302 }

1303 case PPC::ADDItocL:

1304 case PPC::ADDItocL8: {

1305

1307

1308 unsigned Op = MI->getOpcode();

1309

1310

1311

1312 TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)

1313 : PPC::LA);

1314

1315 const MachineOperand &MO = MI->getOperand(2);

1316 assert((Op == PPC::ADDItocL8)

1318 : MO.isGlobal() && "Invalid operand for ADDItocL8.");

1320 "Interposable definitions must use indirect accesses.");

1321

1322

1324

1327

1329 EmitToStreamer(*OutStreamer, TmpInst);

1330 return;

1331 }

1332 case PPC::ADDISgotTprelHA: {

1333

1334

1335 assert(IsPPC64 && "Not supported for 32-bit PowerPC");

1336 const MachineOperand &MO = MI->getOperand(2);

1337 const GlobalValue *GValue = MO.getGlobal();

1338 MCSymbol *MOSymbol = getSymbol(GValue);

1339 const MCExpr *SymGotTprel =

1341 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)

1342 .addReg(MI->getOperand(0).getReg())

1343 .addReg(MI->getOperand(1).getReg())

1344 .addExpr(SymGotTprel));

1345 return;

1346 }

1347 case PPC::LDgotTprelL:

1348 case PPC::LDgotTprelL32: {

1349

1351

1352

1353 TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);

1354 const MachineOperand &MO = MI->getOperand(1);

1355 const GlobalValue *GValue = MO.getGlobal();

1356 MCSymbol *MOSymbol = getSymbol(GValue);

1357 const MCExpr *Exp = symbolWithSpecifier(

1360 EmitToStreamer(*OutStreamer, TmpInst);

1361 return;

1362 }

1363

1364 case PPC::PPC32PICGOT: {

1365 MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));

1366 MCSymbol *GOTRef = OutContext.createTempSymbol();

1367 MCSymbol *NextInstr = OutContext.createTempSymbol();

1368

1369 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL)

1370

1371

1373 const MCExpr *OffsExpr =

1376 OutContext);

1377 OutStreamer->emitLabel(GOTRef);

1378 OutStreamer->emitValue(OffsExpr, 4);

1379 OutStreamer->emitLabel(NextInstr);

1380 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR)

1381 .addReg(MI->getOperand(0).getReg()));

1382 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ)

1383 .addReg(MI->getOperand(1).getReg())

1384 .addImm(0)

1385 .addReg(MI->getOperand(0).getReg()));

1386 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4)

1387 .addReg(MI->getOperand(0).getReg())

1388 .addReg(MI->getOperand(1).getReg())

1389 .addReg(MI->getOperand(0).getReg()));

1390 return;

1391 }

1392 case PPC::PPC32GOT: {

1394 OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));

1395 const MCExpr *SymGotTlsL =

1397 const MCExpr *SymGotTlsHA =

1399 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI)

1400 .addReg(MI->getOperand(0).getReg())

1401 .addExpr(SymGotTlsL));

1402 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)

1403 .addReg(MI->getOperand(0).getReg())

1404 .addReg(MI->getOperand(0).getReg())

1405 .addExpr(SymGotTlsHA));

1406 return;

1407 }

1408 case PPC::ADDIStlsgdHA: {

1409

1410

1411 assert(IsPPC64 && "Not supported for 32-bit PowerPC");

1412 const MachineOperand &MO = MI->getOperand(2);

1413 const GlobalValue *GValue = MO.getGlobal();

1414 MCSymbol *MOSymbol = getSymbol(GValue);

1415 const MCExpr *SymGotTlsGD =

1417 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)

1418 .addReg(MI->getOperand(0).getReg())

1419 .addReg(MI->getOperand(1).getReg())

1420 .addExpr(SymGotTlsGD));

1421 return;

1422 }

1423 case PPC::ADDItlsgdL:

1424

1425

1426 case PPC::ADDItlsgdL32: {

1427

1428

1429 const MachineOperand &MO = MI->getOperand(2);

1430 const GlobalValue *GValue = MO.getGlobal();

1431 MCSymbol *MOSymbol = getSymbol(GValue);

1432 const MCExpr *SymGotTlsGD = symbolWithSpecifier(

1434 EmitToStreamer(*OutStreamer,

1435 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)

1436 .addReg(MI->getOperand(0).getReg())

1437 .addReg(MI->getOperand(1).getReg())

1438 .addExpr(SymGotTlsGD));

1439 return;

1440 }

1441 case PPC::GETtlsMOD32AIX:

1442 case PPC::GETtlsMOD64AIX:

1443

1444

1445

1446 case PPC::GETtlsADDR:

1447

1448

1449 case PPC::GETtlsADDRPCREL:

1450 case PPC::GETtlsADDR32AIX:

1451 case PPC::GETtlsADDR64AIX:

1452

1453

1454

1455 case PPC::GETtlsADDR32: {

1456

1457

1459 return;

1460 }

1461 case PPC::GETtlsTpointer32AIX: {

1462

1463

1464 EmitAIXTlsCallHelper(MI);

1465 return;

1466 }

1467 case PPC::ADDIStlsldHA: {

1468

1469

1470 assert(IsPPC64 && "Not supported for 32-bit PowerPC");

1471 const MachineOperand &MO = MI->getOperand(2);

1472 const GlobalValue *GValue = MO.getGlobal();

1473 MCSymbol *MOSymbol = getSymbol(GValue);

1474 const MCExpr *SymGotTlsLD =

1476 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)

1477 .addReg(MI->getOperand(0).getReg())

1478 .addReg(MI->getOperand(1).getReg())

1479 .addExpr(SymGotTlsLD));

1480 return;

1481 }

1482 case PPC::ADDItlsldL:

1483

1484

1485 case PPC::ADDItlsldL32: {

1486

1487

1488 const MachineOperand &MO = MI->getOperand(2);

1489 const GlobalValue *GValue = MO.getGlobal();

1490 MCSymbol *MOSymbol = getSymbol(GValue);

1491 const MCExpr *SymGotTlsLD = symbolWithSpecifier(

1493 EmitToStreamer(*OutStreamer,

1494 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)

1495 .addReg(MI->getOperand(0).getReg())

1496 .addReg(MI->getOperand(1).getReg())

1497 .addExpr(SymGotTlsLD));

1498 return;

1499 }

1500 case PPC::GETtlsldADDR:

1501

1502

1503 case PPC::GETtlsldADDRPCREL:

1504 case PPC::GETtlsldADDR32: {

1505

1506

1508 return;

1509 }

1510 case PPC::ADDISdtprelHA:

1511

1512

1513 case PPC::ADDISdtprelHA32: {

1514

1515

1516 const MachineOperand &MO = MI->getOperand(2);

1517 const GlobalValue *GValue = MO.getGlobal();

1518 MCSymbol *MOSymbol = getSymbol(GValue);

1519 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_HA);

1520 EmitToStreamer(

1521 *OutStreamer,

1522 MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)

1523 .addReg(MI->getOperand(0).getReg())

1524 .addReg(MI->getOperand(1).getReg())

1525 .addExpr(SymDtprel));

1526 return;

1527 }

1528 case PPC::PADDIdtprel: {

1529

1530

1531 const MachineOperand &MO = MI->getOperand(2);

1532 const GlobalValue *GValue = MO.getGlobal();

1533 MCSymbol *MOSymbol = getSymbol(GValue);

1534 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL);

1535 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::PADDI8)

1536 .addReg(MI->getOperand(0).getReg())

1537 .addReg(MI->getOperand(1).getReg())

1538 .addExpr(SymDtprel));

1539 return;

1540 }

1541

1542 case PPC::ADDIdtprelL:

1543

1544

1545 case PPC::ADDIdtprelL32: {

1546

1547

1548 const MachineOperand &MO = MI->getOperand(2);

1549 const GlobalValue *GValue = MO.getGlobal();

1550 MCSymbol *MOSymbol = getSymbol(GValue);

1551 const MCExpr *SymDtprel = symbolWithSpecifier(MOSymbol, PPC::S_DTPREL_LO);

1552 EmitToStreamer(*OutStreamer,

1553 MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)

1554 .addReg(MI->getOperand(0).getReg())

1555 .addReg(MI->getOperand(1).getReg())

1556 .addExpr(SymDtprel));

1557 return;

1558 }

1559 case PPC::MFOCRF:

1560 case PPC::MFOCRF8:

1561 if (!Subtarget->hasMFOCRF()) {

1562

1563

1564 unsigned NewOpcode =

1565 MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8;

1566 OutStreamer->AddComment(PPCInstPrinter::

1568 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)

1569 .addReg(MI->getOperand(0).getReg()));

1570 return;

1571 }

1572 break;

1573 case PPC::MTOCRF:

1574 case PPC::MTOCRF8:

1575 if (!Subtarget->hasMFOCRF()) {

1576

1577

1578 unsigned NewOpcode =

1579 MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8;

1580 unsigned Mask = 0x80 >> OutContext.getRegisterInfo()

1581 ->getEncodingValue(MI->getOperand(0).getReg());

1582 OutStreamer->AddComment(PPCInstPrinter::

1584 EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode)

1585 .addImm(Mask)

1586 .addReg(MI->getOperand(1).getReg()));

1587 return;

1588 }

1589 break;

1590 case PPC::LD:

1591 case PPC::STD:

1592 case PPC::LWA_32:

1593 case PPC::LWA: {

1594

1595

1596 unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;

1597

1598

1599

1600 for (const MachineOperand &TempMO : MI->operands()) {

1603 TempMO.getOperandNo() == 1)

1604 OpNum = 1;

1605 }

1606 const MachineOperand &MO = MI->getOperand(OpNum);

1610 llvm_unreachable("Global must be word-aligned for LD, STD, LWA!");

1611 }

1612

1613

1614

1615 [[fallthrough]];

1616 }

1617 case PPC::LBZ:

1618 case PPC::LBZ8:

1619 case PPC::LHA:

1620 case PPC::LHA8:

1621 case PPC::LHZ:

1622 case PPC::LHZ8:

1623 case PPC::LWZ:

1624 case PPC::LWZ8:

1625 case PPC::STB:

1626 case PPC::STB8:

1627 case PPC::STH:

1628 case PPC::STH8:

1629 case PPC::STW:

1630 case PPC::STW8:

1631 case PPC::LFS:

1632 case PPC::STFS:

1633 case PPC::LFD:

1634 case PPC::STFD:

1635 case PPC::ADDI8: {

1636

1637

1638

1639

1640 if (!HasAIXSmallLocalTLS)

1641 break;

1642 bool IsMIADDI8 = MI->getOpcode() == PPC::ADDI8;

1643 unsigned OpNum = IsMIADDI8 ? 2 : 1;

1644 const MachineOperand &MO = MI->getOperand(OpNum);

1650

1651 const MCExpr *Expr = getAdjustedFasterLocalExpr(MO, MO.getOffset());

1652 if (Expr)

1654

1655

1656 if (IsMIADDI8)

1658

1659 EmitToStreamer(*OutStreamer, TmpInst);

1660 return;

1661 }

1662

1663 break;

1664 }

1665 case PPC::PseudoEIEIO: {

1666 EmitToStreamer(

1667 *OutStreamer,

1668 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));

1669 EmitToStreamer(

1670 *OutStreamer,

1671 MCInstBuilder(PPC::ORI).addReg(PPC::X2).addReg(PPC::X2).addImm(0));

1672 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::EnforceIEIO));

1673 return;

1674 }

1675 }

1676

1678 EmitToStreamer(*OutStreamer, TmpInst);

1679}

1680

1681

1682

1683

1684

1685

1686

1687const MCExpr *

1688PPCAsmPrinter::getAdjustedFasterLocalExpr(const MachineOperand &MO,

1690

1691

1693 return nullptr;

1694

1695 assert(MO.isGlobal() && "Only expecting a global MachineOperand here!");

1696 const GlobalValue *GValue = MO.getGlobal();

1699 "Only local-[exec|dynamic] accesses are handled!");

1700

1702

1703

1704

1705 const auto TLSVarsMapEntryIter = TLSVarsToAddressMapping.find(GValue);

1706 if (TLSVarsMapEntryIter == TLSVarsToAddressMapping.end())

1707 assert(IsGlobalADeclaration &&

1708 "Only expecting to find extern TLS variables not present in the TLS "

1709 "variable-to-address map!");

1710

1711 unsigned TLSVarAddress =

1712 IsGlobalADeclaration ? 0 : TLSVarsMapEntryIter->second;

1713 ptrdiff_t FinalAddress = (TLSVarAddress + Offset);

1714

1715

1716

1717

1718

1720 getSymbol(GValue),

1722 OutContext);

1725 if (FinalAddress >= 32768) {

1726

1727

1728

1729

1730

1731

1732 ptrdiff_t Delta = ((FinalAddress + 32768) & ~0xFFFF);

1733

1734 [[maybe_unused]] ptrdiff_t InstDisp = TLSVarAddress + Offset - Delta;

1736 ((InstDisp < 32768) && (InstDisp >= -32768)) &&

1737 "Expecting the instruction displacement for local-[exec|dynamic] TLS "

1738 "variables to be between [-32768, 32768)!");

1741 }

1742

1743 return Expr;

1744}

1745

1746void PPCLinuxAsmPrinter::emitGNUAttributes(Module &M) {

1747

1748 Metadata *MD = M.getModuleFlag("float-abi");

1750 if (!FloatABI)

1751 return;

1752 StringRef flt = FloatABI->getString();

1753

1754 if (flt == "doubledouble")

1755 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,

1756 Val_GNU_Power_ABI_HardFloat_DP |

1757 Val_GNU_Power_ABI_LDBL_IBM128);

1758 else if (flt == "ieeequad")

1759 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,

1760 Val_GNU_Power_ABI_HardFloat_DP |

1761 Val_GNU_Power_ABI_LDBL_IEEE128);

1762 else if (flt == "ieeedouble")

1763 OutStreamer->emitGNUAttribute(Tag_GNU_Power_ABI_FP,

1764 Val_GNU_Power_ABI_HardFloat_DP |

1765 Val_GNU_Power_ABI_LDBL_64);

1766}

1767

1768void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {

1769 if (!Subtarget->isPPC64())

1770 return PPCAsmPrinter::emitInstruction(MI);

1771

1772 switch (MI->getOpcode()) {

1773 default:

1774 break;

1775 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {

1776

1777

1778

1779

1780

1781

1782

1783

1784

1785

1786

1787

1788 const Function &F = MF->getFunction();

1789 unsigned Num = 0;

1790 (void)F.getFnAttribute("patchable-function-entry")

1791 .getValueAsString()

1792 .getAsInteger(10, Num);

1793

1794 if (!MAI->isLittleEndian() || Num)

1795 break;

1796 MCSymbol *BeginOfSled = OutContext.createTempSymbol();

1797 MCSymbol *EndOfSled = OutContext.createTempSymbol();

1798 OutStreamer->emitLabel(BeginOfSled);

1799 EmitToStreamer(*OutStreamer,

1800 MCInstBuilder(PPC::B).addExpr(

1802 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));

1803 EmitToStreamer(

1804 *OutStreamer,

1805 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));

1806 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));

1807 EmitToStreamer(*OutStreamer,

1808 MCInstBuilder(PPC::BL8_NOP)

1810 OutContext.getOrCreateSymbol("__xray_FunctionEntry"),

1811 OutContext)));

1812 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));

1813 OutStreamer->emitLabel(EndOfSled);

1814 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER, 2);

1815 break;

1816 }

1817 case TargetOpcode::PATCHABLE_RET: {

1818 unsigned RetOpcode = MI->getOperand(0).getImm();

1819 MCInst RetInst;

1822 MCOperand MCOp;

1825 }

1826

1827 bool IsConditional;

1828 if (RetOpcode == PPC::BCCLR) {

1829 IsConditional = true;

1830 } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 ||

1831 RetOpcode == PPC::TCRETURNai8) {

1832 break;

1833 } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) {

1834 IsConditional = false;

1835 } else {

1836 EmitToStreamer(*OutStreamer, RetInst);

1837 return;

1838 }

1839

1841 if (IsConditional) {

1842

1843

1844

1845

1846

1847

1848

1849

1850

1851

1852

1853

1854

1855

1856

1857

1858

1859

1860 FallthroughLabel = OutContext.createTempSymbol();

1861 EmitToStreamer(

1862 *OutStreamer,

1863 MCInstBuilder(PPC::BCC)

1866 .addReg(MI->getOperand(2).getReg())

1868 RetInst = MCInst();

1870 }

1871

1872

1873

1874

1875

1876

1877

1878

1879

1880

1881

1882

1883 OutStreamer->emitCodeAlignment(Align(8), &getSubtargetInfo());

1884 MCSymbol *BeginOfSled = OutContext.createTempSymbol();

1885 OutStreamer->emitLabel(BeginOfSled);

1886 EmitToStreamer(*OutStreamer, RetInst);

1887 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));

1888 EmitToStreamer(

1889 *OutStreamer,

1890 MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1));

1891 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0));

1892 EmitToStreamer(*OutStreamer,

1893 MCInstBuilder(PPC::BL8_NOP)

1895 OutContext.getOrCreateSymbol("__xray_FunctionExit"),

1896 OutContext)));

1897 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0));

1898 EmitToStreamer(*OutStreamer, RetInst);

1899 if (IsConditional)

1900 OutStreamer->emitLabel(FallthroughLabel);

1901 recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT, 2);

1902 return;

1903 }

1904 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:

1905 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");

1906 case TargetOpcode::PATCHABLE_TAIL_CALL:

1907

1908

1909 llvm_unreachable("Tail call is handled in the normal case. See comments "

1910 "around this assert.");

1911 }

1912 return PPCAsmPrinter::emitInstruction(MI);

1913}

1914

1915void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) {

1916 if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) {

1917 PPCTargetStreamer *TS =

1918 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

1920 }

1921

1922 if (static_cast<const PPCTargetMachine &>(TM).isPPC64() ||

1923 !isPositionIndependent())

1925

1928

1929 OutStreamer->switchSection(OutContext.getELFSection(

1931

1932 MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC"));

1933 MCSymbol *CurrentPos = OutContext.createTempSymbol();

1934

1935 OutStreamer->emitLabel(CurrentPos);

1936

1937

1938

1939 const MCExpr *tocExpr =

1942 OutContext);

1943

1944 OutStreamer->emitAssignment(TOCSym, tocExpr);

1945

1946 OutStreamer->switchSection(getObjFileLowering().getTextSection());

1947}

1948

1949void PPCLinuxAsmPrinter::emitFunctionEntryLabel() {

1950

1951 if (!Subtarget->isPPC64() &&

1952 (!isPositionIndependent() ||

1953 MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC))

1955

1956 if (!Subtarget->isPPC64()) {

1957 const PPCFunctionInfo *PPCFI = MF->getInfo();

1958 if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {

1960 MCSymbol *PICBase = MF->getPICBaseSymbol();

1961 OutStreamer->emitLabel(RelocSymbol);

1962

1963 const MCExpr *OffsExpr =

1966 OutContext),

1968 OutContext);

1969 OutStreamer->emitValue(OffsExpr, 4);

1970 OutStreamer->emitLabel(CurrentFnSym);

1971 return;

1972 } else

1974 }

1975

1976

1978

1979

1980

1981

1983 && !MF->getRegInfo().use_empty(PPC::X2)) {

1984 const PPCFunctionInfo *PPCFI = MF->getInfo();

1985

1986 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));

1988 const MCExpr *TOCDeltaExpr =

1991 OutContext),

1992 OutContext);

1993

1995 OutStreamer->emitValue(TOCDeltaExpr, 8);

1996 }

1998 }

1999

2000

2001 MCSectionSubPair Current = OutStreamer->getCurrentSection();

2002 MCSectionELF *Section = OutStreamer->getContext().getELFSection(

2004 OutStreamer->switchSection(Section);

2005 OutStreamer->emitLabel(CurrentFnSym);

2006 OutStreamer->emitValueToAlignment(Align(8));

2007 MCSymbol *Symbol1 = CurrentFnSymForSize;

2008

2009

2011 8 );

2012 MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC."));

2013

2014 OutStreamer->emitValue(

2016

2017 OutStreamer->emitIntValue(0, 8 );

2018 OutStreamer->switchSection(Current.first, Current.second);

2019}

2020

2021void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {

2022 const DataLayout &DL = getDataLayout();

2023

2024 bool isPPC64 = DL.getPointerSizeInBits() == 64;

2025

2026 PPCTargetStreamer *TS =

2027 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

2028

2029

2030

2031

2032

2033 if (static_cast<const PPCTargetMachine &>(TM).hasGlibcHWCAPAccess())

2034 OutStreamer->emitSymbolValue(

2035 GetExternalSymbolSymbol("__parse_hwcap_and_convert_at_platform"),

2036 MAI->getCodePointerSize());

2037 emitGNUAttributes(M);

2038

2039 if (TOC.empty()) {

2040 const char *Name = isPPC64 ? ".toc" : ".got2";

2041 MCSectionELF *Section = OutContext.getELFSection(

2043 OutStreamer->switchSection(Section);

2044 if (!isPPC64)

2045 OutStreamer->emitValueToAlignment(Align(4));

2046

2047 for (const auto &TOCMapPair : TOC) {

2048 const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;

2049 MCSymbol *const TOCEntryLabel = TOCMapPair.second;

2050

2051 OutStreamer->emitLabel(TOCEntryLabel);

2052 if (isPPC64)

2053 TS->emitTCEntry(*TOCEntryTarget, TOCMapPair.first.second);

2054 else

2055 OutStreamer->emitSymbolValue(TOCEntryTarget, 4);

2056 }

2057 }

2058

2059 PPCAsmPrinter::emitEndOfAsmFile(M);

2060}

2061

2062

2063void PPCLinuxAsmPrinter::emitFunctionBodyStart() {

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2075

2076

2077

2078

2079

2080

2081

2082

2083

2084

2085

2086

2087

2088

2089

2090

2091

2092

2093

2094

2095 const PPCFunctionInfo *PPCFI = MF->getInfo();

2096 const bool UsesX2OrR2 = !MF->getRegInfo().use_empty(PPC::X2) ||

2097 !MF->getRegInfo().use_empty(PPC::R2);

2101 Subtarget->isELFv2ABI() && UsesX2OrR2;

2102

2103

2104

2105

2106 if (NonPCrelGEPRequired || PCrelGEPRequired) {

2107

2108

2109

2111 OutStreamer->emitLabel(GlobalEntryLabel);

2112 const MCSymbolRefExpr *GlobalEntryLabelExp =

2114

2116 MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC."));

2117 const MCExpr *TOCDeltaExpr =

2119 GlobalEntryLabelExp, OutContext);

2120

2121 const MCExpr *TOCDeltaHi =

2123 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)

2124 .addReg(PPC::X2)

2125 .addReg(PPC::X12)

2126 .addExpr(TOCDeltaHi));

2127

2128 const MCExpr *TOCDeltaLo =

2130 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)

2131 .addReg(PPC::X2)

2132 .addReg(PPC::X2)

2133 .addExpr(TOCDeltaLo));

2134 } else {

2136 const MCExpr *TOCOffsetDeltaExpr =

2138 GlobalEntryLabelExp, OutContext);

2139

2140 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD)

2141 .addReg(PPC::X2)

2142 .addExpr(TOCOffsetDeltaExpr)

2143 .addReg(PPC::X12));

2144 EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8)

2145 .addReg(PPC::X2)

2146 .addReg(PPC::X2)

2147 .addReg(PPC::X12));

2148 }

2149

2151 OutStreamer->emitLabel(LocalEntryLabel);

2152 const MCSymbolRefExpr *LocalEntryLabelExp =

2154 const MCExpr *LocalOffsetExp =

2156 GlobalEntryLabelExp, OutContext);

2157

2158 PPCTargetStreamer *TS =

2159 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

2160 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),

2161 LocalOffsetExp);

2163

2164

2165

2166

2167

2168

2169

2170

2171

2172

2173

2174

2175

2176

2177

2178

2179

2180

2181

2182

2183

2184 if (MF->getFrameInfo().hasCalls() || MF->getFrameInfo().hasTailCall() ||

2185 MF->hasInlineAsm() || (!PPCFI->usesTOCBasePtr() && UsesX2OrR2)) {

2186 PPCTargetStreamer *TS =

2187 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

2188 TS->emitLocalEntry(static_cast<MCSymbolELF *>(CurrentFnSym),

2190 }

2191 }

2192}

2193

2194

2195

2196

2197void PPCLinuxAsmPrinter::emitFunctionBodyEnd() {

2198

2199

2200

2201

2202

2203

2204

2205 if (Subtarget->isPPC64()) {

2206 OutStreamer->emitIntValue(0, 4);

2207 OutStreamer->emitIntValue(0, 8);

2208 }

2209}

2210

2211char PPCLinuxAsmPrinter::ID = 0;

2212

2214 "Linux PPC Assembly Printer", false, false)

2215

2219 switch (GV->getLinkage()) {

2220 case GlobalValue::ExternalLinkage:

2221 LinkageAttr = GV->isDeclaration() ? MCSA_Extern : MCSA_Global;

2222 break;

2223 case GlobalValue::LinkOnceAnyLinkage:

2224 case GlobalValue::LinkOnceODRLinkage:

2225 case GlobalValue::WeakAnyLinkage:

2226 case GlobalValue::WeakODRLinkage:

2227 case GlobalValue::ExternalWeakLinkage:

2228 LinkageAttr = MCSA_Weak;

2229 break;

2230 case GlobalValue::AvailableExternallyLinkage:

2231 LinkageAttr = MCSA_Extern;

2232 break;

2233 case GlobalValue::PrivateLinkage:

2234 return;

2235 case GlobalValue::InternalLinkage:

2236 assert(GV->getVisibility() == GlobalValue::DefaultVisibility &&

2237 "InternalLinkage should not have other visibility setting.");

2238 LinkageAttr = MCSA_LGlobal;

2239 break;

2240 case GlobalValue::AppendingLinkage:

2241 llvm_unreachable("Should never emit this");

2242 case GlobalValue::CommonLinkage:

2243 llvm_unreachable("CommonLinkage of XCOFF should not come to this path");

2244 }

2245

2246 assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid.");

2247

2249 if (!TM.getIgnoreXCOFFVisibility()) {

2250 if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())

2251 report_fatal_error(

2252 "Cannot not be both dllexport and non-default visibility");

2253 switch (GV->getVisibility()) {

2254

2255

2256 case GlobalValue::DefaultVisibility:

2257 if (GV->hasDLLExportStorageClass())

2258 VisibilityAttr = MAI->getExportedVisibilityAttr();

2259 break;

2260 case GlobalValue::HiddenVisibility:

2261 VisibilityAttr = MAI->getHiddenVisibilityAttr();

2262 break;

2263 case GlobalValue::ProtectedVisibility:

2264 VisibilityAttr = MAI->getProtectedVisibilityAttr();

2265 break;

2266 }

2267 }

2268

2269

2270 if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&

2272 return;

2273

2274 OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,

2275 VisibilityAttr);

2276}

2277

2278void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {

2279

2280 auto *FnDescSec = static_cast<MCSectionXCOFF *>(

2281 getObjFileLowering().getSectionForFunctionDescriptor(&MF.getFunction(),

2282 TM));

2283 FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4));

2284

2285 CurrentFnDescSym = FnDescSec->getQualNameSymbol();

2286

2288}

2289

2290uint16_t PPCAIXAsmPrinter::getNumberOfVRSaved() {

2291

2292

2293

2294 const PPCSubtarget &Subtarget = MF->getSubtarget();

2295 if (Subtarget.isAIXABI() && Subtarget.hasAltivec() &&

2296 TM.getAIXExtendedAltivecABI()) {

2297 const MachineRegisterInfo &MRI = MF->getRegInfo();

2298 for (unsigned Reg = PPC::V20; Reg <= PPC::V31; ++Reg)

2299 if (MRI.isPhysRegModified(Reg))

2300

2301 return PPC::V31 - Reg + 1;

2302 }

2303 return 0;

2304}

2305

2306void PPCAIXAsmPrinter::emitFunctionBodyEnd() {

2307

2308 if (!TM.getXCOFFTracebackTable())

2309 return;

2310

2311 emitTracebackTable();

2312

2313

2314

2315

2316

2317

2319 (getNumberOfVRSaved() > 0)) {

2320

2321 OutStreamer->switchSection(getObjFileLowering().getCompactUnwindSection());

2324 OutStreamer->emitLabel(EHInfoLabel);

2325

2326

2327 OutStreamer->emitInt32(0);

2328

2329 const DataLayout &DL = MMI->getModule()->getDataLayout();

2330 const unsigned PointerSize = DL.getPointerSize();

2331

2332 OutStreamer->emitValueToAlignment(Align(PointerSize));

2333

2334 OutStreamer->emitIntValue(0, PointerSize);

2335 OutStreamer->emitIntValue(0, PointerSize);

2336 OutStreamer->switchSection(MF->getSection());

2337 }

2338}

2339

2340void PPCAIXAsmPrinter::emitTracebackTable() {

2341

2342

2344 OutStreamer->emitLabel(FuncEnd);

2345

2346 OutStreamer->AddComment("Traceback table begin");

2347

2348 OutStreamer->emitIntValueInHexWithPadding(0, 4 );

2349

2350 SmallString<128> CommentString;

2351 raw_svector_ostream CommentOS(CommentString);

2352

2353 auto EmitComment = [&]() {

2354 OutStreamer->AddComment(CommentOS.str());

2355 CommentString.clear();

2356 };

2357

2358 auto EmitCommentAndValue = [&](uint64_t Value, int Size) {

2359 EmitComment();

2360 OutStreamer->emitIntValueInHexWithPadding(Value, Size);

2361 };

2362

2363 unsigned int Version = 0;

2364 CommentOS << "Version = " << Version;

2365 EmitCommentAndValue(Version, 1);

2366

2367

2368

2369

2370

2371

2374

2375 CommentOS << "Language = "

2377 EmitCommentAndValue(LanguageIdentifier, 1);

2378

2379

2380 uint32_t FirstHalfOfMandatoryField = 0;

2381

2382

2383

2384

2386

2387 const PPCFunctionInfo *FI = MF->getInfo();

2388 const MachineRegisterInfo &MRI = MF->getRegInfo();

2389

2390

2391 for (unsigned Reg = PPC::F0; Reg <= PPC::F31; ++Reg) {

2392 if (MRI.isPhysRegUsed(Reg, true)) {

2394 break;

2395 }

2396 }

2397

2398#define GENBOOLCOMMENT(Prefix, V, Field) \

2399 CommentOS << (Prefix) << ((V) & (TracebackTable::Field##Mask) ? "+" : "-") \

2400 << #Field

2401

2402#define GENVALUECOMMENT(PrefixAndName, V, Field) \

2403 CommentOS << (PrefixAndName) << " = " \

2404 << static_cast(((V) & (TracebackTable::Field##Mask)) >> \

2405 (TracebackTable::Field##Shift))

2406

2407 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsGlobalLinkage);

2408 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsOutOfLineEpilogOrPrologue);

2409 EmitComment();

2410

2411 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasTraceBackTableOffset);

2412 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsInternalProcedure);

2413 EmitComment();

2414

2415 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, HasControlledStorage);

2416 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsTOCless);

2417 EmitComment();

2418

2419 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsFloatingPointPresent);

2420 EmitComment();

2422 IsFloatingPointOperationLogOrAbortEnabled);

2423 EmitComment();

2424

2425 OutStreamer->emitIntValueInHexWithPadding(

2426 (FirstHalfOfMandatoryField & 0x0000ff00) >> 8, 1);

2427

2428

2430

2431 const PPCRegisterInfo *RegInfo = Subtarget->getRegisterInfo();

2433 if (FrameReg == (Subtarget->isPPC64() ? PPC::X31 : PPC::R31))

2435

2436 const SmallVectorImpl &MustSaveCRs = FI->getMustSaveCRs();

2437 if (!MustSaveCRs.empty())

2439

2442

2443 GENBOOLCOMMENT("", FirstHalfOfMandatoryField, IsInterruptHandler);

2444 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsFunctionNamePresent);

2445 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsAllocaUsed);

2446 EmitComment();

2447 GENVALUECOMMENT("OnConditionDirective", FirstHalfOfMandatoryField,

2448 OnConditionDirective);

2449 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsCRSaved);

2450 GENBOOLCOMMENT(", ", FirstHalfOfMandatoryField, IsLRSaved);

2451 EmitComment();

2452 OutStreamer->emitIntValueInHexWithPadding((FirstHalfOfMandatoryField & 0xff),

2453 1);

2454

2455

2456 uint32_t SecondHalfOfMandatoryField = 0;

2457

2460 : 0;

2461

2462 uint32_t FPRSaved = 0;

2463 for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) {

2464 if (MRI.isPhysRegModified(Reg)) {

2465 FPRSaved = PPC::F31 - Reg + 1;

2466 break;

2467 }

2468 }

2471 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, IsBackChainStored);

2472 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, IsFixup);

2473 GENVALUECOMMENT(", NumOfFPRsSaved", SecondHalfOfMandatoryField, FPRSaved);

2474 EmitComment();

2475 OutStreamer->emitIntValueInHexWithPadding(

2476 (SecondHalfOfMandatoryField & 0xff000000) >> 24, 1);

2477

2478

2479

2480

2481

2482 bool HasVectorInst = false;

2483 for (unsigned Reg = PPC::V0; Reg <= PPC::V31; ++Reg)

2484 if (MRI.isPhysRegUsed(Reg, true)) {

2485

2486 HasVectorInst = true;

2487 break;

2488 }

2489

2492

2493 uint16_t NumOfVRSaved = getNumberOfVRSaved();

2494 bool ShouldEmitEHBlock =

2496

2497 if (ShouldEmitEHBlock)

2499

2500 uint32_t GPRSaved = 0;

2501

2502

2503 unsigned GPRBegin = Subtarget->isPPC64() ? PPC::X14 : PPC::R13;

2504 unsigned GPREnd = Subtarget->isPPC64() ? PPC::X31 : PPC::R31;

2505

2506 for (unsigned Reg = GPRBegin; Reg <= GPREnd; ++Reg) {

2507 if (MRI.isPhysRegModified(Reg)) {

2508 GPRSaved = GPREnd - Reg + 1;

2509 break;

2510 }

2511 }

2512

2515

2516 GENBOOLCOMMENT("", SecondHalfOfMandatoryField, HasExtensionTable);

2517 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasVectorInfo);

2518 GENVALUECOMMENT(", NumOfGPRsSaved", SecondHalfOfMandatoryField, GPRSaved);

2519 EmitComment();

2520 OutStreamer->emitIntValueInHexWithPadding(

2521 (SecondHalfOfMandatoryField & 0x00ff0000) >> 16, 1);

2522

2523

2525 SecondHalfOfMandatoryField |=

2528 GENVALUECOMMENT("NumberOfFixedParms", SecondHalfOfMandatoryField,

2529 NumberOfFixedParms);

2530 EmitComment();

2531 OutStreamer->emitIntValueInHexWithPadding(

2532 (SecondHalfOfMandatoryField & 0x0000ff00) >> 8, 1);

2533

2534

2535

2536

2538

2540 SecondHalfOfMandatoryField |=

2543

2544 GENVALUECOMMENT("NumberOfFPParms", SecondHalfOfMandatoryField,

2545 NumberOfFloatingPointParms);

2546 GENBOOLCOMMENT(", ", SecondHalfOfMandatoryField, HasParmsOnStack);

2547 EmitComment();

2548 OutStreamer->emitIntValueInHexWithPadding(SecondHalfOfMandatoryField & 0xff,

2549 1);

2550

2551

2552

2553

2554 if (NumberOfFixedParms || NumberOfFPParms) {

2555 uint32_t ParmsTypeValue = FI->getParmsType();

2556

2557 Expected<SmallString<32>> ParmsType =

2560 ParmsTypeValue, NumberOfFixedParms, NumberOfFPParms,

2562 : XCOFF::parseParmsType(ParmsTypeValue, NumberOfFixedParms,

2563 NumberOfFPParms);

2564

2566 if (ParmsType) {

2567 CommentOS << "Parameter type = " << ParmsType.get();

2568 EmitComment();

2569 }

2570 OutStreamer->emitIntValueInHexWithPadding(ParmsTypeValue,

2571 sizeof(ParmsTypeValue));

2572 }

2573

2574 OutStreamer->AddComment("Function size");

2576 MCSymbol *FuncSectSym = getObjFileLowering().getFunctionEntryPointSymbol(

2578 OutStreamer->emitAbsoluteSymbolDiff(FuncEnd, FuncSectSym, 4);

2579 }

2580

2581

2584

2587

2590 int16_t NameLength = Name.size();

2591 CommentOS << "Function name len = "

2592 << static_cast<unsigned int>(NameLength);

2593 EmitCommentAndValue(NameLength, 2);

2594 OutStreamer->AddComment("Function Name");

2595 OutStreamer->emitBytes(Name);

2596 }

2597

2600 OutStreamer->AddComment("AllocaUsed");

2601 OutStreamer->emitIntValueInHex(AllocReg, sizeof(AllocReg));

2602 }

2603

2605 uint16_t VRData = 0;

2606 if (NumOfVRSaved) {

2607

2610

2611

2612

2613

2614

2616 }

2617

2618

2621

2622

2626

2627 if (HasVectorInst)

2629

2630 GENVALUECOMMENT("NumOfVRsSaved", VRData, NumberOfVRSaved);

2633 EmitComment();

2634 OutStreamer->emitIntValueInHexWithPadding((VRData & 0xff00) >> 8, 1);

2635

2636 GENVALUECOMMENT("NumOfVectorParams", VRData, NumberOfVectorParms);

2638 EmitComment();

2639 OutStreamer->emitIntValueInHexWithPadding(VRData & 0x00ff, 1);

2640

2642

2643 Expected<SmallString<32>> VecParmsType =

2646 if (VecParmsType) {

2647 CommentOS << "Vector Parameter type = " << VecParmsType.get();

2648 EmitComment();

2649 }

2650 OutStreamer->emitIntValueInHexWithPadding(VecParmTypeValue,

2651 sizeof(VecParmTypeValue));

2652

2653 CommentOS << "Padding";

2654 EmitCommentAndValue(0, 2);

2655 }

2656

2657 uint8_t ExtensionTableFlag = 0;

2659 if (ShouldEmitEHBlock)

2660 ExtensionTableFlag |= ExtendedTBTableFlag::TB_EH_INFO;

2663 ExtensionTableFlag |= ExtendedTBTableFlag::TB_SSP_CANARY;

2664

2665 CommentOS << "ExtensionTableFlag = "

2667 EmitCommentAndValue(ExtensionTableFlag, sizeof(ExtensionTableFlag));

2668 }

2669

2670 if (ExtensionTableFlag & ExtendedTBTableFlag::TB_EH_INFO) {

2671 auto &Ctx = OutStreamer->getContext();

2674 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock);

2675 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(

2676 getObjFileLowering().getTOCBaseSection())

2677 ->getQualNameSymbol();

2678 const MCExpr *Exp =

2681

2682 const DataLayout &DL = getDataLayout();

2683 OutStreamer->emitValueToAlignment(Align(4));

2684 OutStreamer->AddComment("EHInfo Table");

2685 OutStreamer->emitValue(Exp, DL.getPointerSize());

2686 }

2687#undef GENBOOLCOMMENT

2688#undef GENVALUECOMMENT

2689}

2690

2694

2695

2696

2697 .Case("llvm.used", true)

2698

2699 .Case("llvm.compiler.used", true)

2701}

2702

2705 .Cases({"llvm.global_ctors", "llvm.global_dtors"}, true)

2707}

2708

2709uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) {

2711 return getAliasOffset(GA->getAliasee());

2715 if (!CBE)

2716 return 0;

2720 if (RHS)

2722 return RHS->getValue();

2723 }

2724 return 0;

2725}

2726

2728

2729

2732 "GlobalVariables with an alignment requirement stricter than TOC entry "

2733 "size not supported by the toc data transformation.");

2734

2736 assert(GVType->isSized() && "A GlobalVariable's size must be known to be "

2737 "supported by the toc data transformation.");

2739 PointerSize * 8)

2741 "A GlobalVariable with size larger than a TOC entry is not currently "

2742 "supported by the toc data transformation.");

2745 "currently supported by the toc data transformation.");

2746}

2747

2748void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {

2749

2751 return;

2752

2753

2754 if (GV->getSection() == "llvm.metadata")

2755 return;

2756

2757

2758

2762 TOCDataGlobalVars.push_back(GV);

2763 return;

2764 }

2765

2766 emitGlobalVariableHelper(GV);

2767}

2768

2769void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {

2771 "Unhandled intrinsic global variable.");

2772

2775

2776 auto *GVSym = static_cast<MCSymbolXCOFF *>(getSymbol(GV));

2777

2779 emitLinkage(GV, GVSym);

2780 return;

2781 }

2782

2783 SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);

2785 !GVKind.isThreadLocal())

2787 "not supported yet.");

2788

2789

2790 if (isVerbose()) {

2793 false, GV->getParent());

2794 OutStreamer->getCommentOS() << '\n';

2795 }

2796 }

2797

2798 auto *Csect = static_cast<MCSectionXCOFF *>(

2799 getObjFileLowering().SectionForGlobal(GV, GVKind, TM));

2800

2801

2802 OutStreamer->switchSection(Csect);

2803

2805

2806

2809 Align Alignment = GV->getAlign().value_or(DL.getPreferredAlign(GV));

2811 GVSym->setStorageClass(

2813

2815 OutStreamer->emitZeros(Size);

2818 "BSS local toc-data already handled and TLS variables "

2819 "incompatible with XMC_TD");

2820 OutStreamer->emitXCOFFLocalCommonSymbol(

2821 OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,

2822 GVSym, Alignment);

2823 } else {

2824 OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);

2825 }

2826 return;

2827 }

2828

2829 MCSymbol *EmittedInitSym = GVSym;

2830

2831

2832 emitLinkage(GV, EmittedInitSym);

2833 for (const GlobalAlias *GA : GOAliasMap[GV])

2834 emitLinkage(GA, getSymbol(GA));

2835

2836 emitAlignment(getGVAlignment(GV, DL), GV);

2837

2838

2839

2840 if (!TM.getDataSections() || GV->hasSection()) {

2842 OutStreamer->emitLabel(EmittedInitSym);

2843 }

2844

2845

2846 if (!GOAliasMap[GV].size()) {

2847 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer());

2848 return;

2849 }

2850

2851

2852

2853 AliasMapTy AliasList;

2854 for (const GlobalAlias *GA : GOAliasMap[GV])

2855 AliasList[getAliasOffset(GA->getAliasee())].push_back(GA);

2856

2857

2858 emitGlobalConstant(GV->getDataLayout(), GV->getInitializer(),

2859 &AliasList);

2860}

2861

2862void PPCAIXAsmPrinter::emitFunctionDescriptor() {

2863 const DataLayout &DL = getDataLayout();

2864 const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;

2865

2866 MCSectionSubPair Current = OutStreamer->getCurrentSection();

2867

2868 OutStreamer->switchSection(

2869 static_cast<MCSymbolXCOFF *>(CurrentFnDescSym)->getRepresentedCsect());

2870

2871

2872 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])

2873 OutStreamer->emitLabel(getSymbol(Alias));

2874

2875

2877 PointerSize);

2878

2879 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(

2880 getObjFileLowering().getTOCBaseSection())

2881 ->getQualNameSymbol();

2883 PointerSize);

2884

2885 OutStreamer->emitIntValue(0, PointerSize);

2886

2887 OutStreamer->switchSection(Current.first, Current.second);

2888}

2889

2890void PPCAIXAsmPrinter::emitFunctionEntryLabel() {

2891

2892

2894 PPCAsmPrinter::emitFunctionEntryLabel();

2895

2896

2897 for (const GlobalAlias *Alias : GOAliasMap[&MF->getFunction()])

2898 OutStreamer->emitLabel(

2899 getObjFileLowering().getFunctionEntryPointSymbol(Alias, TM));

2900}

2901

2902void PPCAIXAsmPrinter::emitPGORefs(Module &M) {

2903 if (!OutContext.hasXCOFFSection(

2904 "__llvm_prf_cnts",

2906 return;

2907

2908

2909

2910

2911

2912

2913

2914 bool HasNonZeroLengthPrfCntsSection = false;

2915 const DataLayout &DL = M.getDataLayout();

2916 for (GlobalVariable &GV : M.globals())

2917 if (GV.hasSection() && GV.getSection() == "__llvm_prf_cnts" &&

2918 DL.getTypeAllocSize(GV.getValueType()) > 0) {

2919 HasNonZeroLengthPrfCntsSection = true;

2920 break;

2921 }

2922

2923 if (HasNonZeroLengthPrfCntsSection) {

2924 MCSection *CntsSection = OutContext.getXCOFFSection(

2927 true);

2928

2929 OutStreamer->switchSection(CntsSection);

2930 if (OutContext.hasXCOFFSection(

2931 "__llvm_prf_data",

2933 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");

2934 OutStreamer->emitXCOFFRefDirective(S);

2935 }

2936 if (OutContext.hasXCOFFSection(

2937 "__llvm_prf_names",

2939 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");

2940 OutStreamer->emitXCOFFRefDirective(S);

2941 }

2942 if (OutContext.hasXCOFFSection(

2943 "__llvm_prf_vnds",

2945 MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");

2946 OutStreamer->emitXCOFFRefDirective(S);

2947 }

2948 }

2949}

2950

2951void PPCAIXAsmPrinter::emitGCOVRefs() {

2952 if (!OutContext.hasXCOFFSection(

2953 "__llvm_gcov_ctr_section",

2955 return;

2956

2957 MCSection *CtrSection = OutContext.getXCOFFSection(

2960 true);

2961

2962 OutStreamer->switchSection(CtrSection);

2965 if (OutContext.hasXCOFFSection(

2966 "__llvm_covinit",

2967 XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {

2968 const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers

2969 ? "__llvm_covinit[RO]"

2970 : "__llvm_covinit[RW]";

2971 MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);

2972 OutStreamer->emitXCOFFRefDirective(S);

2973 }

2974}

2975

2976void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {

2977

2978

2979 if (M.empty() && TOCDataGlobalVars.empty())

2980 return;

2981

2982 emitPGORefs(M);

2983 emitGCOVRefs();

2984

2985

2986 OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());

2987

2988 PPCTargetStreamer *TS =

2989 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

2990

2991 for (auto &I : TOC) {

2992 MCSectionXCOFF *TCEntry;

2993

2994

2995

2996

2997

2999 (Subtarget->hasAIXShLibTLSModelOpt() &&

3001 SmallString<128> Name;

3002 StringRef Prefix = ".";

3004 Name += static_cast<const MCSymbolXCOFF *>(I.first.first)

3005 ->getSymbolTableName();

3006 MCSymbol *S = OutContext.getOrCreateSymbol(Name);

3007 TCEntry = static_cast<MCSectionXCOFF *>(

3008 getObjFileLowering().getSectionForTOCEntry(S, TM));

3009 } else {

3010 TCEntry = static_cast<MCSectionXCOFF *>(

3011 getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));

3012 }

3013 OutStreamer->switchSection(TCEntry);

3014

3015 OutStreamer->emitLabel(I.second);

3016 TS->emitTCEntry(*I.first.first, I.first.second);

3017 }

3018

3019

3020

3021

3022 for (const auto *GV : TOCDataGlobalVars) {

3023 if (!GV->hasCommonLinkage())

3024 emitGlobalVariableHelper(GV);

3025 }

3026 for (const auto *GV : TOCDataGlobalVars) {

3027 if (GV->hasCommonLinkage())

3028 emitGlobalVariableHelper(GV);

3029 }

3030}

3031

3032bool PPCAIXAsmPrinter::doInitialization(Module &M) {

3033 const bool Result = PPCAsmPrinter::doInitialization(M);

3034

3035

3036 const Triple &Target = TM.getTargetTriple();

3038

3039

3040 for (auto &F : M) {

3043 if (FunCpuId > TargetCpuId)

3044 TargetCpuId = FunCpuId;

3045 }

3046

3047

3048

3049 if (!TargetCpuId) {

3050 StringRef TargetCPU = TM.getTargetCPU();

3053 }

3054

3055 PPCTargetStreamer *TS =

3056 static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());

3058

3059 auto setCsectAlignment = [this](const GlobalObject *GO) {

3060

3061 if (GO->isDeclarationForLinker())

3062 return;

3063

3064 SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM);

3065 auto *Csect = static_cast<MCSectionXCOFF *>(

3066 getObjFileLowering().SectionForGlobal(GO, GOKind, TM));

3067

3068 Align GOAlign = getGVAlignment(GO, GO->getDataLayout());

3069 Csect->ensureMinAlignment(GOAlign);

3070 };

3071

3072

3073

3074

3075 uint64_t TLSVarAddress = 0;

3076 auto DL = M.getDataLayout();

3077 for (const auto &G : M.globals()) {

3078 if (G.isThreadLocal() && G.isDeclaration()) {

3079 TLSVarAddress = alignTo(TLSVarAddress, getGVAlignment(&G, DL));

3080 TLSVarsToAddressMapping[&G] = TLSVarAddress;

3081 TLSVarAddress += DL.getTypeAllocSize(G.getValueType());

3082 }

3083 }

3084

3085

3086

3087

3088 for (const auto &G : M.globals()) {

3090 continue;

3091

3093

3094

3095 if (FormatIndicatorAndUniqueModId.empty()) {

3097 if (UniqueModuleId != "")

3098

3099

3100

3101 FormatIndicatorAndUniqueModId = "clang_" + UniqueModuleId.substr(1);

3102 else {

3103

3104

3105 auto CurTime =

3106 std::chrono::duration_caststd::chrono::nanoseconds(

3107 std::chrono::steady_clock::now().time_since_epoch())

3108 .count();

3109 FormatIndicatorAndUniqueModId =

3113 }

3114 }

3115

3116 emitSpecialLLVMGlobal(&G);

3117 continue;

3118 }

3119

3120 setCsectAlignment(&G);

3121 std::optionalCodeModel::Model OptionalCodeModel = G.getCodeModel();

3122 if (OptionalCodeModel)

3124 *OptionalCodeModel);

3125 }

3126

3127 for (const auto &F : M)

3128 setCsectAlignment(&F);

3129

3130

3131 for (const auto &Alias : M.aliases()) {

3132 const GlobalObject *Aliasee = Alias.getAliaseeObject();

3133 if (!Aliasee)

3135 "alias without a base object is not yet supported on AIX");

3136

3138 report_fatal_error("Aliases to common variables are not allowed on AIX:"

3139 "\n\tAlias attribute for " +

3140 Alias.getName() + " is invalid because " +

3141 Aliasee->getName() + " is common.",

3142 false);

3143 }

3144

3145 const GlobalVariable *GVar =

3147 if (GVar) {

3148 std::optionalCodeModel::Model OptionalCodeModel = GVar->getCodeModel();

3149 if (OptionalCodeModel)

3151 *OptionalCodeModel);

3152 }

3153

3154 GOAliasMap[Aliasee].push_back(&Alias);

3155 }

3156

3158}

3159

3160void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {

3161 switch (MI->getOpcode()) {

3162 default:

3163 break;

3164 case PPC::TW:

3165 case PPC::TWI:

3166 case PPC::TD:

3167 case PPC::TDI: {

3168 if (MI->getNumOperands() < 5)

3169 break;

3170 const MachineOperand &LangMO = MI->getOperand(3);

3171 const MachineOperand &ReasonMO = MI->getOperand(4);

3172 if (!LangMO.isImm() || !ReasonMO.isImm())

3173 break;

3174 MCSymbol *TempSym = OutContext.createNamedTempSymbol();

3175 OutStreamer->emitLabel(TempSym);

3176 OutStreamer->emitXCOFFExceptDirective(

3177 CurrentFnSym, TempSym, LangMO.getImm(), ReasonMO.getImm(),

3178 Subtarget->isPPC64() ? MI->getMF()->getInstructionCount() * 8

3179 : MI->getMF()->getInstructionCount() * 4,

3181 break;

3182 }

3183 case PPC::GETtlsMOD32AIX:

3184 case PPC::GETtlsMOD64AIX:

3185 case PPC::GETtlsTpointer32AIX:

3186 case PPC::GETtlsADDR64AIX:

3187 case PPC::GETtlsADDR32AIX: {

3188

3189

3192 ExtSymSDNodeSymbols.insert(TlsGetAddr);

3193 break;

3194 }

3195 case PPC::BL8:

3196 case PPC::BL:

3197 case PPC::BL8_NOP:

3198 case PPC::BL_NOP: {

3199 const MachineOperand &MO = MI->getOperand(0);

3201 auto *S = static_cast<MCSymbolXCOFF *>(

3202 OutContext.getOrCreateSymbol(MO.getSymbolName()));

3203 ExtSymSDNodeSymbols.insert(S);

3204 }

3205 } break;

3206 case PPC::BL_TLS:

3207 case PPC::BL8_TLS:

3208 case PPC::BL8_TLS_:

3209 case PPC::BL8_NOP_TLS:

3211 case PPC::TAILB:

3212 case PPC::TAILB8:

3213 case PPC::TAILBA:

3214 case PPC::TAILBA8:

3215 case PPC::TAILBCTR:

3216 case PPC::TAILBCTR8:

3217 if (MI->getOperand(0).isSymbol())

3218 report_fatal_error("Tail call for extern symbol not yet supported.");

3219 break;

3220 case PPC::DST:

3221 case PPC::DST64:

3222 case PPC::DSTT:

3223 case PPC::DSTT64:

3224 case PPC::DSTST:

3225 case PPC::DSTST64:

3226 case PPC::DSTSTT:

3227 case PPC::DSTSTT64:

3228 EmitToStreamer(

3229 *OutStreamer,

3230 MCInstBuilder(PPC::ORI).addReg(PPC::R0).addReg(PPC::R0).addImm(0));

3231 return;

3232 }

3233 return PPCAsmPrinter::emitInstruction(MI);

3234}

3235

3236bool PPCAIXAsmPrinter::doFinalization(Module &M) {

3237

3239

3240

3241

3242 auto *Sec = OutContext.getObjectFileInfo()->getTextSection();

3243 OutStreamer->switchSectionNoPrint(Sec);

3244 MCSymbol *Sym = Sec->getEndSymbol(OutContext);

3245 OutStreamer->emitLabel(Sym);

3246 }

3247

3248 for (MCSymbol *Sym : ExtSymSDNodeSymbols)

3249 OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);

3250 return PPCAsmPrinter::doFinalization(M);

3251}

3252

3256

3257 if (P <= 20)

3258 return P;

3259

3260 if (P < 81)

3261 return 20 + (P - 20) * 16;

3262

3263 if (P <= 1124)

3264 return 1004 + (P - 81);

3265

3266 if (P < 64512)

3267 return 2047 + (P - 1124) * 33878;

3268

3269 return 2147482625u + (P - 64512);

3270}

3271

3273

3274

3275

3276

3277

3278

3279

3280

3281

3282

3283

3284

3285

3287

3288 std::string PrioritySuffix;

3291 return PrioritySuffix;

3292}

3293

3294void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL,

3295 const Constant *List, bool IsCtor) {

3297 preprocessXXStructorList(DL, List, Structors);

3298 if (Structors.empty())

3299 return;

3300

3301 unsigned Index = 0;

3302 for (Structor &S : Structors) {

3304 S.Func = CE->getOperand(0);

3305

3308 (IsCtor ? llvm::Twine("__sinit") : llvm::Twine("__sterm")) +

3310 llvm::Twine("_", FormatIndicatorAndUniqueModId) +

3313 }

3314}

3315

3316void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV,

3317 unsigned Encoding) {

3318 if (GV) {

3319 TOCEntryType GlobalType = TOCType_GlobalInternal;

3324 GlobalType = TOCType_GlobalExternal;

3325 MCSymbol *TypeInfoSym = TM.getSymbol(GV);

3326 MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType);

3327 const MCSymbol *TOCBaseSym = static_cast<const MCSectionXCOFF *>(

3328 getObjFileLowering().getTOCBaseSection())

3329 ->getQualNameSymbol();

3330 auto &Ctx = OutStreamer->getContext();

3331 const MCExpr *Exp =

3334 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding));

3335 } else

3336 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding));

3337}

3338

3339

3340

3341static AsmPrinter *

3343 std::unique_ptr &&Streamer) {

3345 return new PPCAIXAsmPrinter(tm, std::move(Streamer));

3346

3347 return new PPCLinuxAsmPrinter(tm, std::move(Streamer));

3348}

3349

3350void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {

3351 const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");

3353 return;

3354

3355 std::string S;

3356 raw_string_ostream RSOS(S);

3357 for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {

3359 assert(N->getNumOperands() == 1 &&

3360 "llvm.commandline metadata entry can have only one operand");

3362

3363

3364 RSOS << "@(#)opt " << MDS->getString() << "\n";

3365 RSOS.write('\0');

3366 }

3367 OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());

3368}

3369

3370char PPCAIXAsmPrinter::ID = 0;

3371

3373 "AIX PPC Assembly Printer", false, false)

3374

3375

3377LLVMInitializePowerPCAsmPrinter() {

3386}

unsigned const MachineRegisterInfo * MRI

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

static AMDGPUMCExpr::Specifier getSpecifier(unsigned MOFlags)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

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

#define LLVM_EXTERNAL_VISIBILITY

static bool hasDebugInfo(const MachineFunction *MF)

Module.h This file contains the declarations for the Module class.

static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)

Machine Check Debug Module

This file implements a map that provides insertion order iteration.

Promote Memory to Register

static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type)

Definition PPCAsmPrinter.cpp:454

static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV)

Definition PPCAsmPrinter.cpp:2703

static bool isSpecialLLVMGlobalArrayToSkip(const GlobalVariable *GV)

Definition PPCAsmPrinter.cpp:2691

#define GENBOOLCOMMENT(Prefix, V, Field)

static MCSymbol * getMCSymbolForTOCPseudoMO(const MachineOperand &MO, AsmPrinter &AP)

Map a machine operand for a TOC pseudo-machine instruction to its corresponding MCSymbol.

Definition PPCAsmPrinter.cpp:755

static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM)

Definition PPCAsmPrinter.cpp:497

static AsmPrinter * createPPCAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)

Definition PPCAsmPrinter.cpp:3342

static PPCAsmPrinter::TOCEntryType getTOCEntryTypeForMO(const MachineOperand &MO)

Definition PPCAsmPrinter.cpp:772

static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)

Definition PPCAsmPrinter.cpp:481

static std::string convertToSinitPriority(int Priority)

Definition PPCAsmPrinter.cpp:3272

static MCSymbol * createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc)

This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX.

Definition PPCAsmPrinter.cpp:661

#define GENVALUECOMMENT(PrefixAndName, V, Field)

static unsigned mapToSinitPriority(int P)

Definition PPCAsmPrinter.cpp:3253

static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV)

Definition PPCAsmPrinter.cpp:2727

static cl::opt< bool > EnableSSPCanaryBitInTB("aix-ssp-tb-bit", cl::init(false), cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden)

PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

Provides a library for accessing information about this process and other processes on the operating ...

static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG, const RISCVSubtarget &Subtarget)

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)

This file implements a set that has insertion order iteration characteristics.

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 driving class for all asm writers.

MCSymbol * getSymbol(const GlobalValue *GV) const

virtual MCSymbol * GetCPISymbol(unsigned CPID) const

Return the symbol for the specified constant pool entry.

virtual void SetupMachineFunction(MachineFunction &MF)

This should be called when a new MachineFunction is being processed from runOnMachineFunction.

virtual void emitStartOfAsmFile(Module &)

This virtual method can be overridden by targets that want to emit something at the start of their fi...

MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const

Return the symbol for the specified jump table entry.

bool doInitialization(Module &M) override

Set up the AsmPrinter when we are working on a new module.

bool runOnMachineFunction(MachineFunction &MF) override

Emit the specified function out to the OutStreamer.

MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const

Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.

virtual void emitFunctionEntryLabel()

EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.

virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)

Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.

LLVM_ABI unsigned getPointerSize(unsigned AS=0) const

The pointer representation size in bytes, rounded up to a whole number of bytes.

TypeSize getTypeSizeInBits(Type *Ty) const

Size examples:

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)

If a parent module is specified, the alias is automatically inserted into the end of the specified mo...

StringRef getSection() const

Get the custom section of this global if it has one.

bool hasSection() const

Check if this global has a custom object file section.

LinkageTypes getLinkage() const

bool hasPrivateLinkage() const

ThreadLocalMode getThreadLocalMode() const

bool isDeclarationForLinker() const

Module * getParent()

Get the module that this global value is contained inside of...

LLVM_ABI const DataLayout & getDataLayout() const

Get the data layout of the module this global belongs to.

bool hasCommonLinkage() const

bool hasAppendingLinkage() const

LinkageTypes

An enumeration for the kinds of linkage for global values.

@ ExternalLinkage

Externally visible function.

@ AvailableExternallyLinkage

Available for inspection, not emission.

@ ExternalWeakLinkage

ExternalWeak linkage description.

Type * getValueType() const

bool hasAttribute(Attribute::AttrKind Kind) const

Return true if the attribute exists.

bool hasInitializer() const

Definitions have initializers, declarations don't.

std::optional< CodeModel::Model > getCodeModel() const

Get the custom code model of this global if it has one.

MaybeAlign getAlign() const

Returns the alignment of the given variable.

static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

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 const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)

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

Context object for machine code objects.

void addOperand(const MCOperand Op)

void setOpcode(unsigned Op)

const MCOperand & getOperand(unsigned i) const

static MCOperand createExpr(const MCExpr *Val)

MCRegister getReg() const

Returns the register number.

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

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

void setPerSymbolCodeModel(MCSymbolXCOFF::CodeModel Model)

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.

LLVM_ABI StringRef getString() const

MachineInstrBundleIterator< const MachineInstr > const_iterator

LLVM_ABI MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

uint64_t getStackSize() const

Return the number of bytes that must be allocated to hold all of the fixed size frame objects.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

MCSection * getSection() const

Returns the Section this function belongs to.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

bool isCPI() const

isCPI - Tests if this is a MO_ConstantPoolIndex operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

bool isSymbol() const

isSymbol - Tests if this is a MO_ExternalSymbol operand.

bool isJTI() const

isJTI - Tests if this is a MO_JumpTableIndex operand.

const BlockAddress * getBlockAddress() const

unsigned getTargetFlags() const

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

MachineOperandType getType() const

getType - Returns the MachineOperandType for this operand.

const char * getSymbolName() const

bool isBlockAddress() const

isBlockAddress - Tests if this is a MO_BlockAddress operand.

Register getReg() const

getReg - Returns the register number.

@ MO_Immediate

Immediate operand.

@ MO_ConstantPoolIndex

Address of indexed Constant in Constant Pool.

@ MO_GlobalAddress

Address of a global value.

@ MO_BlockAddress

Address of a basic block.

@ MO_MachineBasicBlock

MachineBasicBlock reference.

@ MO_Register

Register operand.

@ MO_JumpTableIndex

Address of indexed Jump Table for switch.

int64_t getOffset() const

Return the offset from the symbol in this operand.

iterator find(const KeyT &Key)

LLVM_ABI MDNode * getOperand(unsigned i) const

LLVM_ABI unsigned getNumOperands() const

uint64_t getTOCSaveOffset() const

getTOCSaveOffset - Return the previous frame offset to save the TOC register – 64-bit SVR4 ABI only.

uint32_t getParmsType() const

MCSymbol * getPICOffsetSymbol(MachineFunction &MF) const

const SmallVectorImpl< Register > & getMustSaveCRs() const

unsigned getFloatingPointParmsNum() const

bool isAIXFuncUseTLSIEForLD() const

MCSymbol * getGlobalEPSymbol(MachineFunction &MF) const

MCSymbol * getLocalEPSymbol(MachineFunction &MF) const

unsigned getVectorParmsNum() const

int getVarArgsFrameIndex() const

bool usesTOCBasePtr() const

bool hasVectorParms() const

uint32_t getVecExtParmsType() const

MCSymbol * getTOCOffsetSymbol(MachineFunction &MF) const

unsigned getFixedParmsNum() const

static const char * getRegisterName(MCRegister Reg)

static bool hasTLSFlag(unsigned TF)

Register getFrameRegister(const MachineFunction &MF) const override

bool is32BitELFABI() const

const PPCFrameLowering * getFrameLowering() const override

bool isUsingPCRelativeCalls() const

CodeModel::Model getCodeModel(const TargetMachine &TM, const GlobalValue *GV) const

Calculates the effective code model for argument GV.

const PPCRegisterInfo * getRegisterInfo() const override

bool isGVIndirectSymbol(const GlobalValue *GV) const

True if the GV will be accessed via an indirect symbol.

virtual void emitAbiVersion(int AbiVersion)

virtual void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset)

virtual void emitTCEntry(const MCSymbol &S, PPCMCExpr::Specifier Kind)

virtual void emitMachine(StringRef CPU)

bool isThreadBSSLocal() const

static SectionKind getText()

static SectionKind getData()

bool isThreadLocal() const

bool isGlobalWriteableData() const

bool insert(const value_type &X)

Insert a new element into the SetVector.

void push_back(const T &Elt)

LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)

Generate a stackmap record for a patchpoint instruction.

LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)

Generate a stackmap record for a stackmap instruction.

StringRef - Represent a constant reference to a string, i.e.

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr bool empty() const

empty - Check if the string is empty.

A switch()-like statement whose cases are string literals.

StringSwitch & Case(StringLiteral S, T Value)

StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)

static bool ShouldSetSSPCanaryBitInTB(const MachineFunction *MF)

static MCSymbol * getEHInfoTableSymbol(const MachineFunction *MF)

static XCOFF::StorageClass getStorageClassForGlobal(const GlobalValue *GV)

static bool ShouldEmitEHBlock(const MachineFunction *MF)

Primary interface to the complete machine description for the target machine.

const Triple & getTargetTriple() const

CodeModel::Model getCodeModel() const

Returns the code model.

bool isOSAIX() const

Tests whether the OS is AIX.

The instances of the Type class are immutable: once they are created, they are never changed.

bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const

Return true if it makes sense to take the size of this type.

LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const

Implement operator<< on Value.

LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const

Returns an alignment of the pointer value.

LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const

Print the name of this Value out to the specified raw_ostream.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

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

A raw_ostream that writes to an std::string.

static LLVM_ABI Pid getProcessId()

Get the process's identifier.

#define llvm_unreachable(msg)

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

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

Flag

These should be considered private to the implementation of the MCInstrDesc class.

@ MO_TLSLDM_FLAG

MO_TLSLDM_FLAG - on AIX the ML relocation type is only valid for a reference to a TOC symbol from the...

@ MO_TPREL_PCREL_FLAG

MO_TPREL_PCREL_FLAG = MO_PCREL_FLAG | MO_TPREL_FLAG.

@ MO_GOT_TPREL_PCREL_FLAG

MO_GOT_TPREL_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...

@ MO_TLSGDM_FLAG

MO_TLSGDM_FLAG - If this bit is set the symbol reference is relative to the region handle of TLS Gene...

@ MO_TLSLD_FLAG

MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to TLS Local Dynamic model.

@ MO_TPREL_FLAG

MO_TPREL_FLAG - If this bit is set, the symbol reference is relative to the thread pointer and the sy...

@ MO_GOT_TLSLD_PCREL_FLAG

MO_GOT_TLSLD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...

@ MO_TLSGD_FLAG

MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to TLS General Dynamic model for ...

@ MO_GOT_TLSGD_PCREL_FLAG

MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set they should produce the reloc...

LLVM_ABI StringRef getNormalizedPPCTargetCPU(const Triple &T, StringRef CPUName="")

Predicate

Predicate - These are "(BI << 5) | BO" for various predicates.

const char * stripRegisterPrefix(const char *RegName)

stripRegisterPrefix - This method strips the character prefix from a register name so that only the n...

Predicate InvertPredicate(Predicate Opcode)

Invert the specified predicate. != -> ==, < -> >=.

static bool isVRRegister(MCRegister Reg)

static bool isVFRegister(MCRegister Reg)

@ CE

Windows NT (Windows on ARM)

void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)

LLVM_ABI SmallString< 32 > getExtendedTBTableFlagString(uint8_t Flag)

LLVM_ABI XCOFF::CFileCpuId getCpuID(StringRef CPU)

LLVM_ABI Expected< SmallString< 32 > > parseParmsTypeWithVecInfo(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum, unsigned VectorParmsNum)

LLVM_ABI Expected< SmallString< 32 > > parseParmsType(uint32_t Value, unsigned FixedParmsNum, unsigned FloatingParmsNum)

LLVM_ABI Expected< SmallString< 32 > > parseVectorParmsType(uint32_t Value, unsigned ParmsNum)

@ TCPU_INVALID

Invalid id - assumes POWER for old objects.

StorageMappingClass

Storage Mapping Class definitions.

@ XMC_RO

Read Only Constant.

@ XMC_TD

Scalar data item in the TOC.

LLVM_ABI StringRef getTCPUString(XCOFF::CFileCpuId TCPU)

LLVM_ABI StringRef getNameForTracebackTableLanguageId(TracebackTable::LanguageID LangId)

constexpr uint8_t AllocRegNo

@ XTY_SD

Csect definition for initialized storage.

@ XTY_ER

External reference.

initializer< Ty > init(const Ty &Val)

unsigned combineHashValue(unsigned a, unsigned b)

Simplistic combination of 32-bit hash values into 32-bit hash values.

constexpr uint64_t PointerSize

aarch64 pointer size.

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

FunctionAddr VTableAddr Value

Target & getThePPC64LETarget()

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

decltype(auto) dyn_cast(const From &Val)

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

bool LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &OutMO, AsmPrinter &AP)

Target & getThePPC32Target()

std::string utostr(uint64_t X, bool isNeg=false)

auto dyn_cast_or_null(const Y &Val)

FunctionAddr VTableAddr uintptr_t uintptr_t Version

LLVM_ABI std::string getUniqueModuleId(Module *M)

Produce a unique identifier for this module by taking the MD5 sum of the names of the module's strong...

void LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)

LLVM_ABI raw_ostream & dbgs()

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

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)

format_hex_no_prefix - Output N as a fixed width hexadecimal.

Target & getThePPC64Target()

LLVM_ABI uint64_t get_threadid()

Return the current thread id, as used in various OS system calls.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

DWARFExpression::Operation Op

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

constexpr int32_t SignExtend32(uint32_t X)

Sign-extend the number in the bottom B bits of X to a 32-bit integer.

Target & getThePPC32LETarget()

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

decltype(auto) cast(const From &Val)

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

std::pair< MCSection *, uint32_t > MCSectionSubPair

std::string itostr(int64_t X)

@ MCSA_Extern

.extern (XCOFF)

@ MCSA_Invalid

Not a valid directive.

Implement std::hash so that hash_code can be used in STL containers.

constexpr uint64_t value() const

This is a hole in the type system and should not be abused.

static bool isEqual(const TOCKey &A, const TOCKey &B)

Definition PPCAsmPrinter.cpp:121

std::pair< const MCSymbol *, PPCMCExpr::Specifier > TOCKey

Definition PPCAsmPrinter.cpp:110

static unsigned getHashValue(const TOCKey &PairVal)

Definition PPCAsmPrinter.cpp:116

static TOCKey getTombstoneKey()

Definition PPCAsmPrinter.cpp:113

static TOCKey getEmptyKey()

Definition PPCAsmPrinter.cpp:112

An information struct used to provide DenseMap with the various necessary components for a given valu...

Align valueOrOne() const

For convenience, returns a valid alignment or 1 if undefined.

static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)

RegisterAsmPrinter - Register an AsmPrinter implementation for the given target.

static constexpr uint32_t FPRSavedMask

static constexpr uint16_t NumberOfVRSavedMask

static constexpr uint8_t NumberOfFloatingPointParmsShift

static constexpr uint32_t NumberOfFixedParmsMask

static constexpr uint16_t HasVMXInstructionMask

static constexpr uint32_t IsLRSavedMask

static constexpr uint16_t HasVarArgsMask

static constexpr uint32_t IsAllocaUsedMask

static constexpr uint16_t IsVRSavedOnStackMask

static constexpr uint16_t NumberOfVectorParmsMask

static constexpr uint32_t IsFloatingPointPresentMask

static constexpr uint32_t FPRSavedShift

static constexpr uint32_t NumberOfFloatingPointParmsMask

static constexpr uint32_t HasControlledStorageMask

static constexpr uint32_t HasExtensionTableMask

static constexpr uint32_t HasTraceBackTableOffsetMask

static constexpr uint32_t IsCRSavedMask

static constexpr uint8_t NumberOfFixedParmsShift

static constexpr uint32_t GPRSavedMask

static constexpr uint8_t NumberOfVectorParmsShift

static constexpr uint32_t HasParmsOnStackMask

static constexpr uint32_t IsFunctionNamePresentMask

static constexpr uint32_t IsBackChainStoredMask

static constexpr uint32_t IsInterruptHandlerMask

static constexpr uint32_t HasVectorInfoMask

static constexpr uint8_t NumberOfVRSavedShift

static constexpr uint32_t GPRSavedShift