diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2018-03-02 20:39:30 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2018-03-02 20:39:30 +0000 |
commit | 5eb64110d241cf2506f54ade3c2693beed42dd8f (patch) | |
tree | 7ae56e435fdaeb9440ac5068e1317ad465f6130a /llvm/lib | |
parent | 32063888700f57bf57ede4f24efb727fd3f284c5 (diff) | |
download | bcm5719-llvm-5eb64110d241cf2506f54ade3c2693beed42dd8f.tar.gz bcm5719-llvm-5eb64110d241cf2506f54ade3c2693beed42dd8f.zip |
[SystemZ] Support stackmaps and patchpoints
This adds back-end support for the @llvm.experimental.stackmap and
@llvm.experimental.patchpoint intrinsics.
llvm-svn: 326611
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 129 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 17 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.h | 1 |
4 files changed, 157 insertions, 1 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index b39245b20b3..bd99fabb48c 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -460,6 +460,14 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { } break; + case TargetOpcode::STACKMAP: + LowerSTACKMAP(*MI); + return; + + case TargetOpcode::PATCHPOINT: + LowerPATCHPOINT(*MI, Lower); + return; + default: Lower.lower(MI, LoweredMI); break; @@ -467,6 +475,123 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, LoweredMI); } + +// Emit the largest nop instruction smaller than or equal to NumBytes +// bytes. Return the size of nop emitted. +static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, + unsigned NumBytes, const MCSubtargetInfo &STI) { + if (NumBytes < 2) { + llvm_unreachable("Zero nops?"); + return 0; + } + else if (NumBytes < 4) { + OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCRAsm) + .addImm(0).addReg(SystemZ::R0D), STI); + return 2; + } + else if (NumBytes < 6) { + OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCAsm) + .addImm(0).addReg(0).addImm(0).addReg(0), + STI); + return 4; + } + else { + MCSymbol *DotSym = OutContext.createTempSymbol(); + const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); + OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BRCLAsm) + .addImm(0).addExpr(Dot), STI); + OutStreamer.EmitLabel(DotSym); + return 6; + } +} + +void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { + const SystemZInstrInfo *TII = + static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo()); + + unsigned NumNOPBytes = MI.getOperand(1).getImm(); + + SM.recordStackMap(MI); + assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); + + // Scan ahead to trim the shadow. + unsigned ShadowBytes = 0; + const MachineBasicBlock &MBB = *MI.getParent(); + MachineBasicBlock::const_iterator MII(MI); + ++MII; + while (ShadowBytes < NumNOPBytes) { + if (MII == MBB.end() || + MII->getOpcode() == TargetOpcode::PATCHPOINT || + MII->getOpcode() == TargetOpcode::STACKMAP) + break; + ShadowBytes += TII->getInstSizeInBytes(*MII); + if (MII->isCall()) + break; + ++MII; + } + + // Emit nops. + while (ShadowBytes < NumNOPBytes) + ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, + getSubtargetInfo()); +} + +// Lower a patchpoint of the form: +// [<def>], <id>, <numBytes>, <target>, <numArgs> +void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, + SystemZMCInstLower &Lower) { + SM.recordPatchPoint(MI); + PatchPointOpers Opers(&MI); + + unsigned EncodedBytes = 0; + const MachineOperand &CalleeMO = Opers.getCallTarget(); + + if (CalleeMO.isImm()) { + uint64_t CallTarget = CalleeMO.getImm(); + if (CallTarget) { + unsigned ScratchIdx = -1; + unsigned ScratchReg = 0; + do { + ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); + ScratchReg = MI.getOperand(ScratchIdx).getReg(); + } while (ScratchReg == SystemZ::R0D); + + // Materialize the call target address + EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) + .addReg(ScratchReg) + .addImm(CallTarget & 0xFFFFFFFF)); + EncodedBytes += 6; + if (CallTarget >> 32) { + EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) + .addReg(ScratchReg) + .addImm(CallTarget >> 32)); + EncodedBytes += 6; + } + + EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) + .addReg(SystemZ::R14D) + .addReg(ScratchReg)); + EncodedBytes += 2; + } + } else if (CalleeMO.isGlobal()) { + const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); + EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) + .addReg(SystemZ::R14D) + .addExpr(Expr)); + EncodedBytes += 6; + } + + // Emit padding. + unsigned NumBytes = Opers.getNumPatchBytes(); + assert(NumBytes >= EncodedBytes && + "Patchpoint can't request size less than the length of a call."); + assert((NumBytes - EncodedBytes) % 2 == 0 && + "Invalid number of NOP bytes requested!"); + while (EncodedBytes < NumBytes) + EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, + getSubtargetInfo()); +} + // Convert a SystemZ-specific constant pool modifier into the associated // MCSymbolRefExpr variant kind. static MCSymbolRefExpr::VariantKind @@ -521,6 +646,10 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } +void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { + SM.serializeToStackMapSection(); +} + // Force static initialization. extern "C" void LLVMInitializeSystemZAsmPrinter() { RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h index fe8c88fe23e..cb88ec32f83 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h @@ -11,7 +11,9 @@ #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZASMPRINTER_H #include "SystemZTargetMachine.h" +#include "SystemZMCInstLower.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -22,20 +24,33 @@ class Module; class raw_ostream; class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter { +private: + StackMaps SM; + public: SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) - : AsmPrinter(TM, std::move(Streamer)) {} + : AsmPrinter(TM, std::move(Streamer)), SM(*this) {} // Override AsmPrinter. StringRef getPassName() const override { return "SystemZ Assembly Printer"; } void EmitInstruction(const MachineInstr *MI) override; void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override; + void EmitEndOfAsmFile(Module &M) override; bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS) override; + + bool doInitialization(Module &M) override { + SM.reset(); + return AsmPrinter::doInitialization(M); + } + +private: + void LowerSTACKMAP(const MachineInstr &MI); + void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower); }; } // end namespace llvm diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index d069cd5d7ae..e5cf3630033 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -983,6 +983,13 @@ LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, #include "SystemZGenCallingConv.inc" +const MCPhysReg *SystemZTargetLowering::getScratchRegisters( + CallingConv::ID) const { + static const MCPhysReg ScratchRegs[] = { SystemZ::R0D, SystemZ::R1D, + SystemZ::R14D, 0 }; + return ScratchRegs; +} + bool SystemZTargetLowering::allowTruncateForTailCall(Type *FromType, Type *ToType) const { return isTruncateFree(FromType, ToType); @@ -6806,6 +6813,10 @@ MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( case SystemZ::LTXBRCompare_VecPseudo: return emitLoadAndTestCmp0(MI, MBB, SystemZ::LTXBR); + case TargetOpcode::STACKMAP: + case TargetOpcode::PATCHPOINT: + return emitPatchPoint(MI, MBB); + default: llvm_unreachable("Unexpected instr type to insert"); } diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index be20cd61996..fcb2643b99a 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -470,6 +470,7 @@ public: SelectionDAG &DAG) const override; void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, SelectionDAG &DAG) const override; + const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const override; bool allowTruncateForTailCall(Type *, Type *) const override; bool mayBeEmittedAsTailCall(const CallInst *CI) const override; SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, |