diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 2 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 2 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 25 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 95 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 3 | ||||
-rw-r--r-- | lib/CodeGen/StackMaps.cpp | 13 | ||||
-rw-r--r-- | lib/Target/X86/X86CallingConv.h | 35 | ||||
-rw-r--r-- | lib/Target/X86/X86CallingConv.td | 23 | ||||
-rw-r--r-- | lib/Target/X86/X86FastISel.cpp | 1 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 1 | ||||
-rw-r--r-- | lib/Target/X86/X86InstrInfo.cpp | 10 | ||||
-rw-r--r-- | lib/Target/X86/X86MCInstLower.cpp | 35 | ||||
-rw-r--r-- | lib/Target/X86/X86RegisterInfo.cpp | 6 |
14 files changed, 205 insertions, 47 deletions
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 434376008e..4c9439a3ec 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -558,6 +558,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(x86_64_sysvcc); KEYWORD(x86_64_win64cc); KEYWORD(webkit_jscc); + KEYWORD(anyregcc); KEYWORD(cc); KEYWORD(c); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 079a532da6..ad2cbe39cd 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -1343,6 +1343,7 @@ bool LLParser::ParseOptionalVisibility(unsigned &Res) { /// ::= 'x86_64_sysvcc' /// ::= 'x86_64_win64cc' /// ::= 'webkit_jscc' +/// ::= 'anyregcc' /// ::= 'cc' UINT /// bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) { @@ -1366,6 +1367,7 @@ bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) { case lltok::kw_x86_64_sysvcc: CC = CallingConv::X86_64_SysV; break; case lltok::kw_x86_64_win64cc: CC = CallingConv::X86_64_Win64; break; case lltok::kw_webkit_jscc: CC = CallingConv::WebKit_JS; break; + case lltok::kw_anyregcc: CC = CallingConv::AnyReg; break; case lltok::kw_cc: { unsigned ArbitraryCC; Lex.Lex(); diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index e8389e4024..086ea95273 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -91,7 +91,7 @@ namespace lltok { kw_ptx_kernel, kw_ptx_device, kw_spir_kernel, kw_spir_func, kw_x86_64_sysvcc, kw_x86_64_win64cc, - kw_webkit_jscc, + kw_webkit_jscc, kw_anyregcc, // Attributes: kw_attributes, diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index e107276359..1ca200dc8b 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -211,6 +211,7 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, assert(Node->getMachineOpcode() != TargetOpcode::IMPLICIT_DEF && "IMPLICIT_DEF should have been handled as a special case elsewhere!"); + unsigned NumResults = CountResults(Node); for (unsigned i = 0; i < II.getNumDefs(); ++i) { // If the specific node value is only used by a CopyToReg and the dest reg // is a vreg in the same register class, use the CopyToReg'd destination @@ -218,6 +219,10 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node, unsigned VRBase = 0; const TargetRegisterClass *RC = TRI->getAllocatableClass(TII->getRegClass(II, i, TRI, *MF)); + // If the register class is unknown for the given definition, then try to + // infer one from the value type. + if (!RC && i < NumResults) + RC = TLI->getRegClassFor(Node->getSimpleValueType(i)); if (II.OpInfo[i].isOptionalDef()) { // Optional def must be a physical register. unsigned NumResults = CountResults(Node); @@ -722,10 +727,16 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, const MCInstrDesc &II = TII->get(Opc); unsigned NumResults = CountResults(Node); + unsigned NumDefs = II.getNumDefs(); + + // Handle PATCHPOINT specially and then use the generic code. + if (Opc == TargetOpcode::PATCHPOINT) + NumDefs = NumResults; + unsigned NumImpUses = 0; unsigned NodeOperands = - countOperands(Node, II.getNumOperands() - II.getNumDefs(), NumImpUses); - bool HasPhysRegOuts = NumResults > II.getNumDefs() && II.getImplicitDefs()!=0; + countOperands(Node, II.getNumOperands() - NumDefs, NumImpUses); + bool HasPhysRegOuts = NumResults > NumDefs && II.getImplicitDefs()!=0; #ifndef NDEBUG unsigned NumMIOperands = NodeOperands + NumResults; if (II.isVariadic()) @@ -748,12 +759,12 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, // Emit all of the actual operands of this instruction, adding them to the // instruction as appropriate. - bool HasOptPRefs = II.getNumDefs() > NumResults; + bool HasOptPRefs = NumDefs > NumResults; assert((!HasOptPRefs || !HasPhysRegOuts) && "Unable to cope with optional defs and phys regs defs!"); - unsigned NumSkip = HasOptPRefs ? II.getNumDefs() - NumResults : 0; + unsigned NumSkip = HasOptPRefs ? NumDefs - NumResults : 0; for (unsigned i = NumSkip; i != NodeOperands; ++i) - AddOperand(MIB, Node->getOperand(i), i-NumSkip+II.getNumDefs(), &II, + AddOperand(MIB, Node->getOperand(i), i-NumSkip+NumDefs, &II, VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); // Transfer all of the memory reference descriptions of this instruction. @@ -784,8 +795,8 @@ EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, // Additional results must be physical register defs. if (HasPhysRegOuts) { - for (unsigned i = II.getNumDefs(); i < NumResults; ++i) { - unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()]; + for (unsigned i = NumDefs; i < NumResults; ++i) { + unsigned Reg = II.getImplicitDefs()[i - NumDefs]; if (!Node->hasAnyUseOfValue(i)) continue; // This implicitly defined physreg has a use. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index d8a2cfb64a..913f517d85 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6733,7 +6733,8 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) { /// intrinsic's operands need to participate in the calling convention. std::pair<SDValue, SDValue> SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx, - unsigned NumArgs, SDValue Callee) { + unsigned NumArgs, SDValue Callee, + bool useVoidTy) { TargetLowering::ArgListTy Args; Args.reserve(NumArgs); @@ -6753,9 +6754,10 @@ SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx, Args.push_back(Entry); } - TargetLowering::CallLoweringInfo CLI(getRoot(), CI.getType(), - /*retSExt*/ false, /*retZExt*/ false, /*isVarArg*/ false, /*isInReg*/ false, - NumArgs, CI.getCallingConv(), /*isTailCall*/ false, /*doesNotReturn*/ false, + Type *retTy = useVoidTy ? Type::getVoidTy(*DAG.getContext()) : CI.getType(); + TargetLowering::CallLoweringInfo CLI(getRoot(), retTy, /*retSExt*/ false, + /*retZExt*/ false, /*isVarArg*/ false, /*isInReg*/ false, NumArgs, + CI.getCallingConv(), /*isTailCall*/ false, /*doesNotReturn*/ false, /*isReturnValueUsed*/ CI.use_empty(), Callee, Args, DAG, getCurSDLoc()); const TargetLowering *TLI = TM.getTargetLowering(); @@ -6824,32 +6826,38 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) { /// \brief Lower llvm.experimental.patchpoint directly to its target opcode. void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) { // void|i64 @llvm.experimental.patchpoint.void|i64(i32 <id>, - // i32 <numNopBytes>, - // i8* <target>, i32 <numArgs>, - // [Args...], [live variables...]) - + // i32 <numNopBytes>, + // i8* <target>, + // i32 <numArgs>, + // [Args...], + // [live variables...]) + + unsigned CC = CI.getCallingConv(); + bool isAnyRegCC = CC == CallingConv::AnyReg; + bool hasDef = !CI.getType()->isVoidTy(); SDValue Callee = getValue(CI.getOperand(2)); // <target> // Get the real number of arguments participating in the call <numArgs> unsigned NumArgs = - cast<ConstantSDNode>(getValue(CI.getArgOperand(3)))->getZExtValue(); + cast<ConstantSDNode>(getValue(CI.getArgOperand(3)))->getZExtValue(); // Skip the four meta args: <id>, <numNopBytes>, <target>, <numArgs> assert(CI.getNumArgOperands() >= NumArgs + 4 && "Not enough arguments provided to the patchpoint intrinsic"); + // For AnyRegCC the arguments are lowered later on manually. + unsigned NumCallArgs = isAnyRegCC ? 0 : NumArgs; std::pair<SDValue, SDValue> Result = - LowerCallOperands(CI, 4, NumArgs, Callee); + LowerCallOperands(CI, 4, NumCallArgs, Callee, isAnyRegCC); + // Set the root to the target-lowered call chain. SDValue Chain = Result.second; DAG.setRoot(Chain); SDNode *CallEnd = Chain.getNode(); - if (!CI.getType()->isVoidTy()) { - setValue(&CI, Result.first); - if (CallEnd->getOpcode() == ISD::CopyFromReg) - CallEnd = CallEnd->getOperand(0).getNode(); - } + if (hasDef && (CallEnd->getOpcode() == ISD::CopyFromReg)) + CallEnd = CallEnd->getOperand(0).getNode(); + /// Get a call instruction from the call sequence chain. /// Tail calls are not allowed. assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && @@ -6870,10 +6878,21 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) { Ops.push_back( DAG.getIntPtrConstant(cast<ConstantSDNode>(Callee)->getZExtValue())); - // Adjust <numArgs> to account for any stack arguments. + // Adjust <numArgs> to account for any arguments that have been passed on the + // stack instead. // Call Node: Chain, Target, {Args}, RegMask, [Glue] - unsigned NumCallArgs = Call->getNumOperands() - (hasGlue ? 4 : 3); - Ops.push_back(DAG.getTargetConstant(NumCallArgs, MVT::i32)); + unsigned NumCallRegArgs = Call->getNumOperands() - (hasGlue ? 4 : 3); + NumCallRegArgs = isAnyRegCC ? NumArgs : NumCallRegArgs; + Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, MVT::i32)); + + // Add the calling convention + Ops.push_back(DAG.getTargetConstant(CC, MVT::i32)); + + // Add the arguments we omitted previously. The register allocator should + // place these in any free register. + if (isAnyRegCC) + for (unsigned i = 4, e = NumArgs + 4; i != e; ++i) + Ops.push_back(getValue(CI.getArgOperand(i))); // Push the arguments from the call instruction. SDNode::op_iterator e = hasGlue ? Call->op_end()-2 : Call->op_end()-1; @@ -6906,21 +6925,43 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) { if (hasGlue) Ops.push_back(*(Call->op_end()-1)); - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SDVTList NodeTys; + if (isAnyRegCC && hasDef) { + // Create the return types based on the intrinsic definition + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SmallVector<EVT, 3> ValueVTs; + ComputeValueVTs(TLI, CI.getType(), ValueVTs); + assert(ValueVTs.size() == 1 && "Expected only one return value type."); - // Replace the target specific call node with a STACKMAP node. + // There is always a chain and a glue type at the end + ValueVTs.push_back(MVT::Other); + ValueVTs.push_back(MVT::Glue); + NodeTys = DAG.getVTList(ValueVTs.data(), ValueVTs.size()); + } else + NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + + // Replace the target specific call node with a PATCHPOINT node. MachineSDNode *MN = DAG.getMachineNode(TargetOpcode::PATCHPOINT, getCurSDLoc(), NodeTys, Ops); - // PatchPoint generates no value, so nothing goes in the NodeMap. - // - // FIXME: with anyregcc calling convention it will need to be in the NodeMap - // and replace values. + // Update the NodeMap. + if (hasDef) { + if (isAnyRegCC) + setValue(&CI, SDValue(MN, 0)); + else + setValue(&CI, Result.first); + } // Fixup the consumers of the intrinsic. The chain and glue may be used in the - // call sequence. - DAG.ReplaceAllUsesWith(Call, MN); - + // call sequence. Furthermore the location of the chain and glue can change + // when the AnyReg calling convention is used and the intrinsic returns a + // value. + if (isAnyRegCC && hasDef) { + SDValue From[] = {SDValue(Call, 0), SDValue(Call, 1)}; + SDValue To[] = {SDValue(MN, 1), SDValue(MN, 2)}; + DAG.ReplaceAllUsesOfValuesWith(From, To, 2); + } else + DAG.ReplaceAllUsesWith(Call, MN); DAG.DeleteNode(Call); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 6ecf5a0abb..570f927069 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -622,7 +622,8 @@ public: std::pair<SDValue, SDValue> LowerCallOperands(const CallInst &CI, unsigned ArgIdx, unsigned NumArgs, - SDValue Callee); + SDValue Callee, + bool useVoidTy = false); /// UpdateSplitBlock - When an MBB was split during scheduling, update the /// references that ned to refer to the last resulting block. diff --git a/lib/CodeGen/StackMaps.cpp b/lib/CodeGen/StackMaps.cpp index 51580b479d..89da78294f 100644 --- a/lib/CodeGen/StackMaps.cpp +++ b/lib/CodeGen/StackMaps.cpp @@ -30,7 +30,8 @@ using namespace llvm; void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID, MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE) { + MachineInstr::const_mop_iterator MOE, + bool recordResult) { MCContext &OutContext = AP.OutStreamer.getContext(); MCSymbol *MILabel = OutContext.CreateTempSymbol(); @@ -38,6 +39,16 @@ void StackMaps::recordStackMap(const MachineInstr &MI, uint32_t ID, LocationVec CallsiteLocs; + if (recordResult) { + std::pair<Location, MachineInstr::const_mop_iterator> ParseResult = + OpParser(MI.operands_begin(), llvm::next(MI.operands_begin(), 1)); + + Location &Loc = ParseResult.first; + assert(Loc.LocType == Location::Register && + "Stackmap return location must be a register."); + CallsiteLocs.push_back(Loc); + } + while (MOI != MOE) { std::pair<Location, MachineInstr::const_mop_iterator> ParseResult = OpParser(MOI, MOE); diff --git a/lib/Target/X86/X86CallingConv.h b/lib/Target/X86/X86CallingConv.h new file mode 100644 index 0000000000..e76f9fda2d --- /dev/null +++ b/lib/Target/X86/X86CallingConv.h @@ -0,0 +1,35 @@ +//=== X86CallingConv.h - X86 Custom Calling Convention Routines -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the custom routines for the X86 Calling Convention that +// aren't done by tablegen. +// +//===----------------------------------------------------------------------===// + +#ifndef X86CALLINGCONV_H +#define X86CALLINGCONV_H + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/IR/CallingConv.h" + +namespace llvm { + +inline bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &, + CCValAssign::LocInfo &, ISD::ArgFlagsTy &, + CCState &) { + llvm_unreachable("The AnyReg calling convention is only supported by the " \ + "stackmap and patchpoint intrinsics."); + // gracefully fallback to X86 C calling convention on Release builds. + return false; +} + +} // End llvm namespace + +#endif + diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index f5c8d9fda4..a78b5c0a79 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -160,6 +160,17 @@ def RetCC_X86_64_WebKit_JS : CallingConv<[ CCIfType<[i64], CCAssignToReg<[RAX]>> ]>; +// X86-64 AnyReg return-value convention. No explicit register is specified for +// the return-value. The register allocator is allowed and expected to choose +// any free register. +// +// This calling convention is currently only supported by the stackmap and +// patchpoint intrinsics. All other uses will result in an assert on Debug +// builds. On Release builds we fallback to the X86 C calling convention. +def RetCC_X86_64_AnyReg : CallingConv<[ + CCCustom<"CC_X86_AnyReg_Error"> +]>; + // This is the root return-value convention for the X86-32 backend. def RetCC_X86_32 : CallingConv<[ // If FastCC, use RetCC_X86_32_Fast. @@ -178,6 +189,7 @@ def RetCC_X86_64 : CallingConv<[ // Handle JavaScript calls. CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo<RetCC_X86_64_WebKit_JS>>, + CCIfCC<"CallingConv::AnyReg", CCDelegateTo<RetCC_X86_64_AnyReg>>, // Handle explicit CC selection CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo<RetCC_X86_Win64_C>>, @@ -350,6 +362,16 @@ def CC_X86_64_WebKit_JS : CallingConv<[ CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>> ]>; +// No explicit register is specified for the AnyReg calling convention. The +// register allocator may assign the arguments to any free register. +// +// This calling convention is currently only supported by the stackmap and +// patchpoint intrinsics. All other uses will result in an assert on Debug +// builds. On Release builds we fallback to the X86 C calling convention. +def CC_X86_64_AnyReg : CallingConv<[ + CCCustom<"CC_X86_AnyReg_Error"> +]>; + //===----------------------------------------------------------------------===// // X86 C Calling Convention //===----------------------------------------------------------------------===// @@ -542,6 +564,7 @@ def CC_X86_64 : CallingConv<[ CCIfCC<"CallingConv::GHC", CCDelegateTo<CC_X86_64_GHC>>, CCIfCC<"CallingConv::HiPE", CCDelegateTo<CC_X86_64_HiPE>>, CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo<CC_X86_64_WebKit_JS>>, + CCIfCC<"CallingConv::AnyReg", CCDelegateTo<CC_X86_64_AnyReg>>, CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo<CC_X86_Win64_C>>, CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo<CC_X86_64_C>>, diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 7984e76edd..928dea91b4 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "X86.h" +#include "X86CallingConv.h" #include "X86ISelLowering.h" #include "X86InstrBuilder.h" #include "X86RegisterInfo.h" diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 86ad2621fb..55bfab449a 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -16,6 +16,7 @@ #include "X86ISelLowering.h" #include "Utils/X86ShuffleDecode.h" #include "X86.h" +#include "X86CallingConv.h" #include "X86InstrBuilder.h" #include "X86TargetMachine.h" #include "X86TargetObjectFile.h" diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 369b031113..b81b244828 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -4198,14 +4198,20 @@ static MachineInstr* foldPatchpoint(MachineFunction &MF, const SmallVectorImpl<unsigned> &Ops, int FrameIndex, const TargetInstrInfo &TII) { + bool hasDef = MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && + !MI->getOperand(0).isImplicit(); + unsigned StartIdx = hasDef ? 1 : 0; + MachineInstr *NewMI = MF.CreateMachineInstr(TII.get(MI->getOpcode()), MI->getDebugLoc(), true); MachineInstrBuilder MIB(MF, NewMI); bool isPatchPoint = MI->getOpcode() == TargetOpcode::PATCHPOINT; - unsigned StartIdx = isPatchPoint ? MI->getOperand(3).getImm() + 4 : 2; + StartIdx = isPatchPoint ? + StartIdx + MI->getOperand(StartIdx+3).getImm() + 5 : + StartIdx + 2; - // No need to fold the meta data and function arguments + // No need to fold return, the meta data, and function arguments for (unsigned i = 0; i < StartIdx; ++i) MIB.addOperand(MI->getOperand(i)); diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 92a111843f..fa15114f91 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -780,26 +780,45 @@ static void LowerSTACKMAP(MCStreamer &OutStreamer, static void LowerPATCHPOINT(MCStreamer &OutStreamer, X86MCInstLower &MCInstLowering, StackMaps &SM, - const MachineInstr &MI) -{ - int64_t ID = MI.getOperand(0).getImm(); + const MachineInstr &MI) { + bool hasDef = MI.getOperand(0).isReg() && MI.getOperand(0).isDef() && + !MI.getOperand(0).isImplicit(); + unsigned StartIdx = hasDef ? 1 : 0; +#ifndef NDEBUG + unsigned StartIdx2 = 0, e = MI.getNumOperands(); + while (StartIdx2 < e && MI.getOperand(StartIdx2).isReg() && + MI.getOperand(StartIdx2).isDef() && + !MI.getOperand(StartIdx2).isImplicit()) + ++StartIdx2; + + assert(StartIdx == StartIdx2 && + "Unexpected additonal definition in Patchpoint intrinsic."); +#endif + + int64_t ID = MI.getOperand(StartIdx).getImm(); assert((int32_t)ID == ID && "Stack maps hold 32-bit IDs"); // Get the number of arguments participating in the call. This number was // adjusted during call lowering by subtracting stack args. - int64_t StackMapIdx = MI.getOperand(3).getImm() + 4; - assert(StackMapIdx <= MI.getNumOperands() && "Patchpoint dropped args."); + bool isAnyRegCC = MI.getOperand(StartIdx + 4).getImm() == CallingConv::AnyReg; + assert(((hasDef && isAnyRegCC) || !hasDef) && + "Only Patchpoints with AnyReg calling convention may have a result"); + int64_t StackMapIdx = isAnyRegCC ? StartIdx + 5 : + StartIdx + 5 + MI.getOperand(StartIdx + 3).getImm(); + assert(StackMapIdx <= MI.getNumOperands() && + "Patchpoint intrinsic dropped arguments."); SM.recordStackMap(MI, ID, llvm::next(MI.operands_begin(), StackMapIdx), - getStackMapEndMOP(MI.operands_begin(), MI.operands_end())); + getStackMapEndMOP(MI.operands_begin(), MI.operands_end()), + isAnyRegCC && hasDef); // Emit call. We need to know how many bytes we encoded here. unsigned EncodedBytes = 2; OutStreamer.EmitInstruction(MCInstBuilder(X86::CALL64r) - .addReg(MI.getOperand(2).getReg())); + .addReg(MI.getOperand(StartIdx + 2).getReg())); // Emit padding. - unsigned NumNOPBytes = MI.getOperand(1).getImm(); + unsigned NumNOPBytes = MI.getOperand(StartIdx + 1).getImm(); assert(NumNOPBytes >= EncodedBytes && "Patchpoint can't request size less than the length of a call."); diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 0cb9ac38bc..75987157dc 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -239,6 +239,10 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { case CallingConv::HiPE: return CSR_NoRegs_SaveList; + case CallingConv::WebKit_JS: + case CallingConv::AnyReg: + return CSR_MostRegs_64_SaveList; + case CallingConv::Intel_OCL_BI: { bool HasAVX = TM.getSubtarget<X86Subtarget>().hasAVX(); bool HasAVX512 = TM.getSubtarget<X86Subtarget>().hasAVX512(); @@ -296,6 +300,8 @@ X86RegisterInfo::getCallPreservedMask(CallingConv::ID CC) const { } if (CC == CallingConv::GHC || CC == CallingConv::HiPE) return CSR_NoRegs_RegMask; + if (CC == CallingConv::WebKit_JS || CC == CallingConv::AnyReg) + return CSR_MostRegs_64_RegMask; if (!Is64Bit) return CSR_32_RegMask; if (CC == CallingConv::Cold) |