/// assume that the provided condition will be true.
CallInst *CreateAssumption(Value *Cond);
+ /// \brief Create a call to the experimental.gc.statepoint intrinsic to
+ /// start a new statepoint sequence.
+ CallInst *CreateGCStatepoint(Value *ActualCallee,
+ ArrayRef<Value*> CallArgs,
+ ArrayRef<Value*> DeoptArgs,
+ ArrayRef<Value*> GCArgs,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.result intrinsic to extract
+ /// the result from a call wrapped in a statepoint.
+ CallInst *CreateGCResult(Instruction *Statepoint,
+ Type *ResultType,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.relocate intrinsics to
+ /// project the relocated value of one pointer from the statepoint.
+ CallInst *CreateGCRelocate(Instruction *Statepoint,
+ int BaseOffset,
+ int DerivedOffset,
+ Type *ResultType,
+ const Twine &Name = "");
+
private:
/// \brief Create a call to a masked intrinsic with given Id.
/// Masked intrinsic has only one overloaded type - data type.
}
static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops,
- IRBuilderBase *Builder) {
- CallInst *CI = CallInst::Create(Callee, Ops, "");
+ IRBuilderBase *Builder,
+ const Twine& Name="") {
+ CallInst *CI = CallInst::Create(Callee, Ops, Name);
Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),CI);
Builder->SetInstDebugLocation(CI);
return CI;
Value *TheFn = Intrinsic::getDeclaration(M, (Intrinsic::ID)Id, OverloadedTypes);
return createCallHelper(TheFn, Ops, this);
}
+
+CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
+ ArrayRef<Value*> CallArgs,
+ ArrayRef<Value*> DeoptArgs,
+ ArrayRef<Value*> GCArgs,
+ const Twine& Name) {
+ // Extract out the type of the callee.
+ PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType());
+ assert(isa<FunctionType>(FuncPtrType->getElementType()) &&
+ "actual callee must be a callable value");
+
+
+ Module *M = BB->getParent()->getParent();
+ // Fill in the one generic type'd argument (the function is also vararg)
+ Type *ArgTypes[] = { FuncPtrType };
+ Function *FnStatepoint =
+ Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint,
+ ArgTypes);
+
+ std::vector<llvm::Value *> args;
+ args.push_back(ActualCallee);
+ args.push_back(getInt32(CallArgs.size()));
+ args.push_back(getInt32(0 /*unused*/));
+ args.insert(args.end(), CallArgs.begin(), CallArgs.end());
+ args.push_back(getInt32(DeoptArgs.size()));
+ args.insert(args.end(), DeoptArgs.begin(), DeoptArgs.end());
+ args.insert(args.end(), GCArgs.begin(), GCArgs.end());
+
+ return createCallHelper(FnStatepoint, args, this, Name);
+}
+
+CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,
+ Type *ResultType,
+ const Twine &Name) {
+ Intrinsic::ID ID;
+ if (ResultType->isIntegerTy()) {
+ ID = Intrinsic::experimental_gc_result_int;
+ } else if (ResultType->isFloatingPointTy()) {
+ ID = Intrinsic::experimental_gc_result_float;
+ } else if (ResultType->isPointerTy()) {
+ ID = Intrinsic::experimental_gc_result_ptr;
+ } else {
+ llvm_unreachable("unimplemented result type for gc.result");
+ }
+ Module *M = BB->getParent()->getParent();
+ Type *Types[] = {ResultType};
+ Value *FnGCResult = Intrinsic::getDeclaration(M, ID, Types);
+
+ Value *Args[] = {Statepoint};
+ return createCallHelper(FnGCResult, Args, this, Name);
+}
+
+CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint,
+ int BaseOffset,
+ int DerivedOffset,
+ Type *ResultType,
+ const Twine &Name) {
+ Module *M = BB->getParent()->getParent();
+ Type *Types[] = {ResultType};
+ Value *FnGCRelocate =
+ Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_relocate, Types);
+
+ Value *Args[] = {Statepoint,
+ getInt32(BaseOffset),
+ getInt32(DerivedOffset)};
+ return createCallHelper(FnGCRelocate, Args, this, Name);
+}