LLVM: lib/Target/Sparc/SparcAsmPrinter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

37using namespace llvm;

38

39#define DEBUG_TYPE "asm-printer"

40

41namespace {

42class SparcAsmPrinter : public AsmPrinter {

45 *OutStreamer->getTargetStreamer());

46 }

47

48public:

50 std::unique_ptr Streamer)

52

53 StringRef getPassName() const override { return "Sparc Assembly Printer"; }

54

57

58 void emitFunctionBodyStart() override;

59 void emitInstruction(const MachineInstr *MI) override;

60

63 }

64

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

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

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

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

69

70 void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,

72

74

75private:

77

78public:

79 static char ID;

80};

81}

82

93

99 OutContext);

101 OutContext);

102

107}

108

112{

114 CallInst.setOpcode(SP::CALL);

117}

118

127

138

150

154 EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);

155}

156

160 EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);

161}

162

166 EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);

167}

168

174 EmitSETHI(OutStreamer, hi, RD, STI);

175 EmitOR(OutStreamer, RD, lo, RD, STI);

176}

177

178void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,

180{

182 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));

183

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

186 "%o7 is assigned as destination for getpcx!");

187

189

190

191 if (!isPositionIndependent()) {

192

193 switch(TM.getCodeModel()) {

194 default:

197 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,

198 MCRegOP, OutContext, STI);

199 break;

201 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_H44, ELF::R_SPARC_M44,

202 MCRegOP, OutContext, STI);

204 OutContext));

205 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);

206 MCOperand lo =

208 EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);

209 break;

210 }

212 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HH22, ELF::R_SPARC_HM10,

213 MCRegOP, OutContext, STI);

215 OutContext));

216 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);

217

219 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,

220 RegO7, OutContext, STI);

221 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);

222 }

223 }

224 return;

225 }

226

227 MCSymbol *StartLabel = OutContext.createTempSymbol();

228 MCSymbol *EndLabel = OutContext.createTempSymbol();

229 MCSymbol *SethiLabel = OutContext.createTempSymbol();

230

232

233

234

235

236

237

238

239

240

241 OutStreamer->emitLabel(StartLabel);

243 STI.hasFeature(Sparc::TuneSlowRDPC)) {

245 EmitCall(*OutStreamer, Callee, STI);

246 } else {

247

248

249

250

251 EmitRDPC(*OutStreamer, RegO7, STI);

252 }

253 OutStreamer->emitLabel(SethiLabel);

254 MCOperand hiImm = createPCXRelExprOp(ELF::R_SPARC_PC22, GOTLabel, StartLabel,

255 SethiLabel, OutContext);

256 EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);

257 OutStreamer->emitLabel(EndLabel);

258 MCOperand loImm = createPCXRelExprOp(ELF::R_SPARC_PC10, GOTLabel, StartLabel,

259 EndLabel, OutContext);

260 EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);

261 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);

262}

263

264MCOperand SparcAsmPrinter::lowerOperand(const MachineOperand &MO) const {

266 default:

268 break;

271 break;

273

276

285 default:

289 break;

292 break;

295 break;

298 break;

301 break;

302 }

303

305 if (RelType)

308 }

309

311 break;

312 }

313 return MCOperand();

314}

315

316void SparcAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {

318

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

320 MCOperand MCOp = lowerOperand(MO);

323 }

324}

325

326void SparcAsmPrinter::emitInstruction(const MachineInstr *MI) {

327 Sparc_MC::verifyInstructionPredicates(MI->getOpcode(),

328 getSubtargetInfo().getFeatureBits());

329 if (MI->isBundle()) {

330 const MachineBasicBlock *MBB = MI->getParent();

332 while (I != MBB->instr_end() && I->isInsideBundle()) {

334 ++I;

335 }

336 return;

337 }

338

339 switch (MI->getOpcode()) {

340 default: break;

341 case TargetOpcode::DBG_VALUE:

342

343 return;

344 case SP::CASArr:

345 case SP::SWAPrr:

346 case SP::SWAPri:

347 if (MF->getSubtarget().fixTN0011())

348 OutStreamer->emitCodeAlignment(Align(16), &getSubtargetInfo());

349 break;

350 case SP::GETPCX:

351 LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());

352 return;

353 }

356 do {

357 MCInst TmpInst;

358 lowerToMCInst(&*I, TmpInst);

359 EmitToStreamer(*OutStreamer, TmpInst);

360 } while ((++I != E) && I->isInsideBundle());

361}

362

363void SparcAsmPrinter::emitFunctionBodyStart() {

364 if (!MF->getSubtarget().is64Bit())

365 return;

366

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

368 const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };

369 for (unsigned i = 0; globalRegs[i] != 0; ++i) {

370 unsigned reg = globalRegs[i];

371 if (MRI.use_empty(reg))

372 continue;

373

374 if (reg == SP::G6 || reg == SP::G7)

375 getTargetStreamer().emitSparcRegisterIgnore(reg);

376 else

377 getTargetStreamer().emitSparcRegisterScratch(reg);

378 }

379}

380

381void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,

382 raw_ostream &O) {

383 const DataLayout &DL = getDataLayout();

384 const MachineOperand &MO = MI->getOperand(opNum);

388 break;

389

392 break;

395 return;

397 PrintSymbolOperand(MO, O);

398 break;

401 break;

404 break;

406 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"

408 break;

411 break;

412 default:

414 }

415}

416

417void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,

418 raw_ostream &O) {

420

421 if (MI->getOperand(opNum+1).isReg() &&

422 MI->getOperand(opNum+1).getReg() == SP::G0)

423 return;

424 if (MI->getOperand(opNum+1).isImm() &&

425 MI->getOperand(opNum+1).getImm() == 0)

426 return;

427

428 O << "+";

430}

431

432

433

434bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

435 const char *ExtraCode,

436 raw_ostream &O) {

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

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

439

440 switch (ExtraCode[0]) {

441 default:

442

444 case 'L':

445 case 'H':

446 {

447 const SparcSubtarget &Subtarget = MF->getSubtarget();

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

449 const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();

450 Register MOReg = MO.getReg();

451

453 if (!SP::IntPairRegClass.contains(MOReg)) {

454

455

456

457

458 MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,

459 &SP::IntPairRegClass);

460 if (!MOReg) {

461 SMLoc Loc;

462 OutContext.reportError(

463 Loc, "Hi part of pair should point to an even-numbered register");

464 OutContext.reportError(

465 Loc, "(note that in some cases it might be necessary to manually "

466 "bind the input/output registers instead of relying on "

467 "automatic allocation)");

468 return true;

469 }

470 }

471

472 HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);

473 LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);

474

476 switch (ExtraCode[0]) {

477 case 'L':

478 Reg = LoReg;

479 break;

480 case 'H':

481 Reg = HiReg;

482 break;

483 }

484

486 return false;

487 }

488 case 'f':

489 case 'r':

490 break;

491 }

492 }

493

495

496 return false;

497}

498

499bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,

500 unsigned OpNo,

501 const char *ExtraCode,

502 raw_ostream &O) {

503 if (ExtraCode && ExtraCode[0])

504 return true;

505

506 O << '[';

508 O << ']';

509

510 return false;

511}

512

513char SparcAsmPrinter::ID = 0;

514

515INITIALIZE_PASS(SparcAsmPrinter, "sparc-asm-printer", "Sparc Assembly Printer",

516 false, false)

517

518

520LLVMInitializeSparcAsmPrinter() {

524}

unsigned const MachineRegisterInfo * MRI

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

#define LLVM_EXTERNAL_VISIBILITY

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

Promote Memory to Register

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

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

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

static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)

static MCOperand createPCXRelExprOp(uint16_t Spec, MCSymbol *GOTLabel, MCSymbol *StartLabel, MCSymbol *CurLabel, MCContext &OutContext)

Definition SparcAsmPrinter.cpp:94

static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)

Definition SparcAsmPrinter.cpp:89

static void EmitSHL(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:163

static void EmitCall(MCStreamer &OutStreamer, MCOperand &Callee, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:109

static MCOperand createSparcMCOperand(uint16_t Kind, MCSymbol *Sym, MCContext &OutContext)

Definition SparcAsmPrinter.cpp:83

static void EmitSETHI(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:128

static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:151

static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:139

static void EmitRDPC(MCStreamer &OutStreamer, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:119

static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, uint16_t HiKind, uint16_t LoKind, MCOperand &RD, MCContext &OutContext, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:169

static void EmitADD(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &RD, const MCSubtargetInfo &STI)

Definition SparcAsmPrinter.cpp:157

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

This class is intended to be used as a driving class for all asm writers.

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.

This class represents a function call, abstracting a target machine's calling convention.

Binary assembler expressions.

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

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.

Instances of this class represent a single low-level machine instruction.

void addOperand(const MCOperand Op)

void setOpcode(unsigned Op)

Instances of this class represent operands of the MCInst class.

static MCOperand createExpr(const MCExpr *Val)

static MCOperand createReg(MCRegister Reg)

static MCOperand createImm(int64_t Val)

Wrapper class representing physical registers. Should be passed by value.

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

Streaming machine code generation interface.

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

Emit the given Instruction into the current section.

Generic base class for all target subtargets.

bool hasFeature(unsigned Feature) const

const Triple & getTargetTriple() const

Represent a reference to a symbol from inside an expression.

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

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

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

print - Print the value to the stream OS.

LLVM_ABI MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

instr_iterator instr_end()

Instructions::const_iterator const_instr_iterator

Representation of each machine instruction.

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

const MDNode * getMetadata() const

MachineBasicBlock * getMBB() const

const BlockAddress * getBlockAddress() const

unsigned getTargetFlags() const

MachineOperandType getType() const

getType - Returns the MachineOperandType for this operand.

const char * getSymbolName() const

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_RegisterMask

Mask of preserved registers.

@ MO_BlockAddress

Address of a basic block.

@ MO_MachineBasicBlock

MachineBasicBlock reference.

@ MO_Register

Register operand.

@ MO_ExternalSymbol

Name of external global symbol.

@ MO_Metadata

Metadata reference (for debug info)

static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=SP::NoRegAltName)

const SparcRegisterInfo * getRegisterInfo() const override

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

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

bool isSPARC64() const

Tests whether the target is 64-bit SPARC (big endian).

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

#define llvm_unreachable(msg)

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

constexpr char Align[]

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

unsigned ID

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

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

This is an optimization pass for GlobalISel generic memory operations.

Target & getTheSparcTarget()

Target & getTheSparcV9Target()

@ Sub

Subtraction of integers.

Target & getTheSparcelTarget()

ArrayRef< int > lo(ArrayRef< int > Vuu)

RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...