Index: llvm/trunk/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/trunk/include/llvm/IR/IRBuilder.h +++ llvm/trunk/include/llvm/IR/IRBuilder.h @@ -439,6 +439,28 @@ /// 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 CallArgs, + ArrayRef DeoptArgs, + ArrayRef 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. Index: llvm/trunk/lib/IR/IRBuilder.cpp =================================================================== --- llvm/trunk/lib/IR/IRBuilder.cpp +++ llvm/trunk/lib/IR/IRBuilder.cpp @@ -53,8 +53,9 @@ } static CallInst *createCallHelper(Value *Callee, ArrayRef 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; @@ -209,3 +210,70 @@ Value *TheFn = Intrinsic::getDeclaration(M, (Intrinsic::ID)Id, OverloadedTypes); return createCallHelper(TheFn, Ops, this); } + +CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine& Name) { + // Extract out the type of the callee. + PointerType *FuncPtrType = cast(ActualCallee->getType()); + assert(isa(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 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); +}