Add IRBuilder routines for gc.statepoints, gc.results, and gc.relocates
authorPhilip Reames <listmail@philipreames.com>
Tue, 30 Dec 2014 05:55:58 +0000 (05:55 +0000)
committerPhilip Reames <listmail@philipreames.com>
Tue, 30 Dec 2014 05:55:58 +0000 (05:55 +0000)
Nothing particularly interesting, just adding infrastructure for use by in tree users and out of tree users.

Note: These were extracted out of a working frontend, but they have not been well tested in isolation.

Differential Revision: http://reviews.llvm.org/D6807

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224981 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/IRBuilder.h
lib/IR/IRBuilder.cpp

index e564ca52adf0de2ad13aa795883f834a71e2df2d..fda663844a67d95790c19e11f162fde24ded098c 100644 (file)
@@ -439,6 +439,28 @@ public:
   /// 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.
index 31dc52e3fc2d03891d174cda2e18bd69493142df..9782ecc4d14a3f49f106819dab5b09cc9c05c5b7 100644 (file)
@@ -53,8 +53,9 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) {
 }
 
 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;  
@@ -209,3 +210,70 @@ CallInst *IRBuilderBase::CreateMaskedIntrinsic(unsigned Id,
   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);
+}