LLVM support for vector quad bit permute and gather instructions through builtins
[oota-llvm.git] / include / llvm / IR / Statepoint.h
index e3e0701312fdbe426f0292d1b82ac92f3be35c83..cd09618e3eee4125342bd20bca25df7e178ba03a 100644 (file)
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CallSite.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
+/// The statepoint intrinsic accepts a set of flags as its third argument.
+/// Valid values come out of this set.
+enum class StatepointFlags {
+  None = 0,
+  GCTransition = 1, ///< Indicates that this statepoint is a transition from
+                    ///< GC-aware code to code that is not GC-aware.
+
+  MaskAll = GCTransition ///< A bitmask that includes all valid flags.
+};
 
 class GCRelocateOperands;
 class ImmutableStatepoint;
@@ -52,7 +62,7 @@ class StatepointBase {
   void *operator new(size_t, unsigned) = delete;
   void *operator new(size_t s) = delete;
 
- protected:
+protected:
   explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
     assert(isStatepoint(I));
   }
@@ -60,16 +70,45 @@ class StatepointBase {
     assert(isStatepoint(CS));
   }
 
- public:
+public:
   typedef typename CallSiteTy::arg_iterator arg_iterator;
 
+  enum {
+    IDPos = 0,
+    NumPatchBytesPos = 1,
+    ActualCalleePos = 2,
+    NumCallArgsPos = 3,
+    FlagsPos = 4,
+    CallArgsBeginPos = 5,
+  };
+
   /// Return the underlying CallSite.
-  CallSiteTy getCallSite() {
-    return StatepointCS;
+  CallSiteTy getCallSite() { return StatepointCS; }
+
+  uint64_t getFlags() const {
+    return cast<ConstantInt>(StatepointCS.getArgument(FlagsPos))
+        ->getZExtValue();
+  }
+
+  /// Return the ID associated with this statepoint.
+  uint64_t getID() {
+    const Value *IDVal = StatepointCS.getArgument(IDPos);
+    return cast<ConstantInt>(IDVal)->getZExtValue();
+  }
+
+  /// Return the number of patchable bytes associated with this statepoint.
+  uint32_t getNumPatchBytes() {
+    const Value *NumPatchBytesVal = StatepointCS.getArgument(NumPatchBytesPos);
+    uint64_t NumPatchBytes =
+      cast<ConstantInt>(NumPatchBytesVal)->getZExtValue();
+    assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!");
+    return NumPatchBytes;
   }
 
   /// Return the value actually being called or invoked.
-  ValueTy *getActualCallee() { return StatepointCS.getArgument(0); }
+  ValueTy *getActualCallee() {
+    return StatepointCS.getArgument(ActualCalleePos);
+  }
 
   /// Return the type of the value returned by the call underlying the
   /// statepoint.
@@ -81,28 +120,18 @@ class StatepointBase {
 
   /// Number of arguments to be passed to the actual callee.
   int getNumCallArgs() {
-    return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+    const Value *NumCallArgsVal = StatepointCS.getArgument(NumCallArgsPos);
+    return cast<ConstantInt>(NumCallArgsVal)->getZExtValue();
   }
 
-  /// Number of additional arguments excluding those intended
-  /// for garbage collection.
-  int getNumTotalVMSArgs() {
-    const Value *NumVMSArgs = StatepointCS.getArgument(3 + getNumCallArgs());
-    return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
-  }
-
-  int callArgsBeginOffset() { return 3; }
-
   typename CallSiteTy::arg_iterator call_args_begin() {
-    // 3 = callTarget, #callArgs, flag
-    int Offset = callArgsBeginOffset();
-    assert(Offset <= (int)StatepointCS.arg_size());
-    return StatepointCS.arg_begin() + Offset;
+    assert(CallArgsBeginPos <= (int)StatepointCS.arg_size());
+    return StatepointCS.arg_begin() + CallArgsBeginPos;
   }
   typename CallSiteTy::arg_iterator call_args_end() {
-    int Offset = callArgsBeginOffset() + getNumCallArgs();
-    assert(Offset <= (int)StatepointCS.arg_size());
-    return StatepointCS.arg_begin() + Offset;
+    auto I = call_args_begin() + getNumCallArgs();
+    assert((StatepointCS.arg_end() - I) >= 0);
+    return I;
   }
 
   /// range adapter for call arguments
@@ -110,13 +139,44 @@ class StatepointBase {
     return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
   }
 
+  /// Number of GC transition args.
+  int getNumTotalGCTransitionArgs() {
+    const Value *NumGCTransitionArgs = *call_args_end();
+    return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
+  }
+  typename CallSiteTy::arg_iterator gc_transition_args_begin() {
+    auto I = call_args_end() + 1;
+    assert((StatepointCS.arg_end() - I) >= 0);
+    return I;
+  }
+  typename CallSiteTy::arg_iterator gc_transition_args_end() {
+    auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs();
+    assert((StatepointCS.arg_end() - I) >= 0);
+    return I;
+  }
+
+  /// range adapter for GC transition arguments
+  iterator_range<arg_iterator> gc_transition_args() {
+    return iterator_range<arg_iterator>(gc_transition_args_begin(),
+                                        gc_transition_args_end());
+  }
+
+  /// Number of additional arguments excluding those intended
+  /// for garbage collection.
+  int getNumTotalVMSArgs() {
+    const Value *NumVMSArgs = *gc_transition_args_end();
+    return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
+  }
+
   typename CallSiteTy::arg_iterator vm_state_begin() {
-    return call_args_end();
+    auto I = gc_transition_args_end() + 1;
+    assert((StatepointCS.arg_end() - I) >= 0);
+    return I;
   }
   typename CallSiteTy::arg_iterator vm_state_end() {
-    int Offset = 3 + getNumCallArgs() + 1 + getNumTotalVMSArgs();
-    assert(Offset <= (int)StatepointCS.arg_size());
-    return StatepointCS.arg_begin() + Offset;
+    auto I = vm_state_begin() + getNumTotalVMSArgs();
+    assert((StatepointCS.arg_end() - I) >= 0);
+    return I;
   }
 
   /// range adapter for vm state arguments
@@ -124,15 +184,7 @@ class StatepointBase {
     return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
   }
 
-  typename CallSiteTy::arg_iterator first_vm_state_stack_begin() {
-    // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
-    //     1st_#stack, 1st_#local, 1st_#monitor
-    return vm_state_begin() + 6;
-  }
-
-  typename CallSiteTy::arg_iterator gc_args_begin() {
-    return vm_state_end();
-  }
+  typename CallSiteTy::arg_iterator gc_args_begin() { return vm_state_end(); }
   typename CallSiteTy::arg_iterator gc_args_end() {
     return StatepointCS.arg_end();
   }
@@ -159,6 +211,8 @@ class StatepointBase {
     // The internal asserts in the iterator accessors do the rest.
     (void)call_args_begin();
     (void)call_args_end();
+    (void)gc_transition_args_begin();
+    (void)gc_transition_args_end();
     (void)vm_state_begin();
     (void)vm_state_end();
     (void)gc_args_begin();
@@ -170,8 +224,7 @@ class StatepointBase {
 /// A specialization of it's base class for read only access
 /// to a gc.statepoint.
 class ImmutableStatepoint
-    : public StatepointBase<const Instruction, const Value,
-                            ImmutableCallSite> {
+    : public StatepointBase<const Instruction, const Value, ImmutableCallSite> {
   typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
       Base;
 
@@ -196,30 +249,23 @@ public:
 class GCRelocateOperands {
   ImmutableCallSite RelocateCS;
 
- public:
-  GCRelocateOperands(const User* U) : RelocateCS(U) {
-    assert(isGCRelocate(U));
-  }
+public:
+  GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); }
   GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
     assert(isGCRelocate(inst));
   }
-  GCRelocateOperands(CallSite CS) : RelocateCS(CS) {
-    assert(isGCRelocate(CS));
-  }
+  GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); }
 
   /// Return true if this relocate is tied to the invoke statepoint.
   /// This includes relocates which are on the unwinding path.
   bool isTiedToInvoke() const {
     const Value *Token = RelocateCS.getArgument(0);
 
-    return isa<ExtractValueInst>(Token) ||
-      isa<InvokeInst>(Token);
+    return isa<ExtractValueInst>(Token) || isa<InvokeInst>(Token);
   }
 
   /// Get enclosed relocate intrinsic
-  ImmutableCallSite getUnderlyingCallSite() {
-    return RelocateCS;
-  }
+  ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; }
 
   /// The statepoint with which this gc.relocate is associated.
   const Instruction *getStatepoint() {
@@ -269,8 +315,8 @@ class GCRelocateOperands {
 
 template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
 std::vector<GCRelocateOperands>
-  StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
-    getRelocates(ImmutableStatepoint &IS) {
+StatepointBase<InstructionTy, ValueTy, CallSiteTy>::getRelocates(
+    ImmutableStatepoint &IS) {
 
   std::vector<GCRelocateOperands> Result;
 
@@ -288,7 +334,7 @@ std::vector<GCRelocateOperands>
 
   // We need to scan thorough exceptional relocations if it is invoke statepoint
   LandingPadInst *LandingPad =
-    cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
+      cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
 
   // Search for extract value from landingpad instruction to which
   // gc relocates will be attached
@@ -303,7 +349,6 @@ std::vector<GCRelocateOperands>
   }
   return Result;
 }
-
 }
 
 #endif