diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index c9a88d7b1c015..fabe5bc226037 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -453,6 +453,10 @@ class AsmPrinter : public MachineFunctionPass { /// function to the current output stream. virtual void emitJumpTableInfo(); + /// Emit jump table annotations correlating each table with its associated + /// indirect branch instruction. + virtual void emitJumpTableAnnotation(const MachineFunction &MF, const MachineInstr &MI); + /// Emit the specified global variable to the .s file. virtual void emitGlobalVariable(const GlobalVariable *GV); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3a8cde7330efc..4563ed98a49ea 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -162,6 +162,10 @@ static cl::opt EmitJumpTableSizesSection( cl::desc("Emit a section containing jump table addresses and sizes"), cl::Hidden, cl::init(false)); +static cl::opt AnnotateJumpTables("annotate-jump-tables", + cl::desc("Annotate jump tables"), + cl::Hidden, cl::init(false)); + STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; @@ -1528,6 +1532,25 @@ void AsmPrinter::emitPseudoProbe(const MachineInstr &MI) { } } +void AsmPrinter::emitJumpTableAnnotation(const MachineFunction &MF, + const MachineInstr &MI) { + if (!AnnotateJumpTables || !TM.getTargetTriple().isOSBinFormatELF()) + return; + + MCSymbol *JTISymbol = GetJTISymbol(MI.getOperand(0).getImm()); + MCSymbol *ProvenanceLabel = OutContext.createTempSymbol("jtp"); + + const MCExpr *OffsetExpr = + MCSymbolRefExpr::create(ProvenanceLabel, OutContext); + const MCExpr *JTISymbolExpr = + MCSymbolRefExpr::create(JTISymbol, OutContext); + + OutStreamer->emitRelocDirective(*OffsetExpr, "BFD_RELOC_NONE", + JTISymbolExpr, SMLoc(), + *OutContext.getSubtargetInfo()); + OutStreamer->emitLabel(ProvenanceLabel); +} + void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) { if (!MF.getTarget().Options.EmitStackSizeSection) return; @@ -1849,8 +1872,7 @@ void AsmPrinter::emitFunctionBody() { OutStreamer->emitRawComment("MEMBARRIER"); break; case TargetOpcode::JUMP_TABLE_DEBUG_INFO: - // This instruction is only used to note jump table debug info, it's - // purely meta information. + emitJumpTableAnnotation(*MF, MI); break; case TargetOpcode::INIT_UNDEF: // This is only used to influence register allocation behavior, no @@ -2821,6 +2843,25 @@ void AsmPrinter::emitJumpTableInfo() { // label differences will be evaluated at write time. for (const MachineBasicBlock *MBB : JTBBs) emitJumpTableEntry(MJTI, MBB, JTI); + + if (AnnotateJumpTables && TM.getTargetTriple().isOSBinFormatELF()) { + // Create a temp symbol for the end of the jump table. + MCSymbol *JTIEndSymbol = createTempSymbol("jt_end"); + OutStreamer->emitLabel(JTIEndSymbol); + + const MCExpr *JTISymbolExpr = + MCSymbolRefExpr::create(JTISymbol, OutContext); + + MCSymbol *JTISymbolForSize = OutContext.getOrCreateSymbol( + "$JTI" + Twine(MF->getFunctionNumber()) + "_" + Twine(JTI)); + OutStreamer->emitAssignment(JTISymbolForSize, JTISymbolExpr); + OutStreamer->emitSymbolAttribute(JTISymbolForSize, MCSA_ELF_TypeObject); + + const MCExpr *SizeExp = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(JTIEndSymbol, OutContext), JTISymbolExpr, + OutContext); + OutStreamer->emitELFSize(JTISymbolForSize, SizeExp); + } } if (EmitJumpTableSizesSection) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 40f030d7b936f..a4c990cce7cc8 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -479,8 +479,10 @@ SDValue TargetLowering::expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr, int JTI, SelectionDAG &DAG) const { SDValue Chain = Value; - // Jump table debug info is only needed if CodeView is enabled. - if (DAG.getTarget().getTargetTriple().isOSBinFormatCOFF()) { + const auto &Triple = DAG.getTarget().getTargetTriple(); + // Jump table debug info is only needed if CodeView is enabled, + // or when adding jump table annotations to ELF objects. + if (Triple.isOSBinFormatCOFF() || Triple.isOSBinFormatELF()) { Chain = DAG.getJumpTableDebugInfo(JTI, Chain, dl); } return DAG.getNode(ISD::BRIND, dl, MVT::Other, Chain, Addr);