summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2018-03-02 20:39:30 +0000
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2018-03-02 20:39:30 +0000
commit5eb64110d241cf2506f54ade3c2693beed42dd8f (patch)
tree7ae56e435fdaeb9440ac5068e1317ad465f6130a /llvm/lib
parent32063888700f57bf57ede4f24efb727fd3f284c5 (diff)
downloadbcm5719-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.cpp129
-rw-r--r--llvm/lib/Target/SystemZ/SystemZAsmPrinter.h17
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.cpp11
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.h1
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,
OpenPOWER on IntegriCloud