Index: lib/Transforms/Scalar/PlaceSafepoints.cpp =================================================================== --- lib/Transforms/Scalar/PlaceSafepoints.cpp +++ lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -901,11 +901,37 @@ Instruction *Token = nullptr; AttributeSet OriginalAttrs; + uint64_t ID; + uint32_t NumPatchBytes; + + AttributeSet AS = CS.getAttributes(); + Attribute AttrID = + AS.getAttribute(AttributeSet::FunctionIndex, "statepoint-id"); + Attribute AttrNumPatchBytes = AS.getAttribute(AttributeSet::FunctionIndex, + "statepoint-num-patch-bytes"); + + bool HasID = AttrID.isStringAttribute() && + !AttrID.getValueAsString().getAsInteger(10, ID); + if (!HasID) + ID = 0xABCDEF00; + + bool HasNumPatchBytes = + AttrNumPatchBytes.isStringAttribute() && + !AttrNumPatchBytes.getValueAsString().getAsInteger(10, NumPatchBytes); + if (!HasNumPatchBytes) + NumPatchBytes = 0; + + Value *StatepointTarget = NumPatchBytes == 0 + ? CS.getCalledValue() + : ConstantPointerNull::get(cast( + CS.getCalledValue()->getType())); + if (CS.isCall()) { CallInst *ToReplace = cast(CS.getInstruction()); CallInst *Call = Builder.CreateGCStatepointCall( - 0xABCDEF00, 0, CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()), - None, None, "safepoint_token"); + ID, NumPatchBytes, StatepointTarget, + makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None, + "safepoint_token"); Call->setTailCall(ToReplace->isTailCall()); Call->setCallingConv(ToReplace->getCallingConv()); @@ -933,7 +959,7 @@ // original block. Builder.SetInsertPoint(ToReplace->getParent()); InvokeInst *Invoke = Builder.CreateGCStatepointInvoke( - 0xABCDEF00, 0, CS.getCalledValue(), ToReplace->getNormalDest(), + ID, NumPatchBytes, StatepointTarget, ToReplace->getNormalDest(), ToReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()), Builder.getInt32(0), None, "safepoint_token"); Index: test/Transforms/PlaceSafepoints/patchable-statepoints.ll =================================================================== --- /dev/null +++ test/Transforms/PlaceSafepoints/patchable-statepoints.ll @@ -0,0 +1,41 @@ +; RUN: opt -place-safepoints -S < %s | FileCheck %s + +declare void @f() +declare i32 @personality_function() + +define void @test_id() gc "statepoint-example" { +; CHECK-LABEL: @test_id( +entry: +; CHECK-LABEL: entry: +; CHECK: invoke i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 100, i32 0, void ()* @f + invoke void @f() "statepoint-id"="100" to label %normal_return unwind label %exceptional_return + +normal_return: + ret void + +exceptional_return: + %landing_pad4 = landingpad {i8*, i32} personality i32 ()* @personality_function cleanup + ret void +} + +define void @test_num_patch_bytes() gc "statepoint-example" { +; CHECK-LABEL: @test_num_patch_bytes( +entry: +; CHECK-LABEL: entry: +; CHECK: invoke i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 99, void ()* null, + invoke void @f() "statepoint-num-patch-bytes"="99" to label %normal_return unwind label %exceptional_return + +normal_return: + ret void + +exceptional_return: + %landing_pad4 = landingpad {i8*, i32} personality i32 ()* @personality_function cleanup + ret void +} + +declare void @do_safepoint() +define void @gc.safepoint_poll() { +entry: + call void @do_safepoint() + ret void +}