mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-12-20 03:17:48 +00:00
Extend the statepoint intrinsic to allow statepoints to be marked as transitions from GC-aware code to code that is not GC-aware.
This changes the shape of the statepoint intrinsic from:
@llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 unused, ...call args, i32 # deopt args, ...deopt args, ...gc args)
to:
@llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 flags, ...call args, i32 # transition args, ...transition args, i32 # deopt args, ...deopt args, ...gc args)
This extension offers the backend the opportunity to insert (somewhat) arbitrary code to manage the transition from GC-aware code to code that is not GC-aware and back.
In order to support the injection of transition code, this extension wraps the STATEPOINT ISD node generated by the usual lowering lowering with two additional nodes: GC_TRANSITION_START and GC_TRANSITION_END. The transition arguments that were passed passed to the intrinsic (if any) are lowered and provided as operands to these nodes and may be used by the backend during code generation.
Eventually, the lowering of the GC_TRANSITION_{START,END} nodes should be informed by the GC strategy in use for the function containing the intrinsic call; for now, these nodes are instead replaced with no-ops.
Differential Revision: http://reviews.llvm.org/D9501
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -701,6 +701,15 @@ namespace ISD {
|
||||
/// is the chain and the second operand is the alloca pointer.
|
||||
LIFETIME_START, LIFETIME_END,
|
||||
|
||||
/// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the
|
||||
/// beginning and end of GC transition sequence, and carry arbitrary
|
||||
/// information that target might need for lowering. The first operand is
|
||||
/// a chain, the rest are specified by the target and not touched by the DAG
|
||||
/// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be
|
||||
/// nested.
|
||||
GC_TRANSITION_START,
|
||||
GC_TRANSITION_END,
|
||||
|
||||
/// BUILTIN_OP_END - This must be the last enum value in this list.
|
||||
/// The target-specific pre-isel opcode values start here.
|
||||
BUILTIN_OP_END
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
#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;
|
||||
@@ -72,6 +81,10 @@ public:
|
||||
/// Return the underlying CallSite.
|
||||
CallSiteTy getCallSite() { return StatepointCS; }
|
||||
|
||||
uint64_t getFlags() const {
|
||||
return cast<ConstantInt>(StatepointCS.getArgument(2))->getZExtValue();
|
||||
}
|
||||
|
||||
/// Return the value actually being called or invoked.
|
||||
ValueTy *getActualCallee() {
|
||||
return StatepointCS.getArgument(ActualCalleePos);
|
||||
@@ -106,16 +119,42 @@ public:
|
||||
return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
|
||||
}
|
||||
|
||||
/// Number of GC transition args.
|
||||
int getNumTotalGCTransitionArgs() {
|
||||
const Value *NumGCTransitionArgs = *gc_transition_args_begin();
|
||||
return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
|
||||
}
|
||||
typename CallSiteTy::arg_iterator gc_transition_args_begin() {
|
||||
int Offset = call_args_end() - StatepointCS.arg_begin();
|
||||
assert(Offset <= (int)StatepointCS.arg_size());
|
||||
return StatepointCS.arg_begin() + Offset;
|
||||
}
|
||||
typename CallSiteTy::arg_iterator gc_transition_args_end() {
|
||||
int Offset = (gc_transition_args_begin() + 1 +
|
||||
getNumTotalGCTransitionArgs()) - StatepointCS.arg_begin();
|
||||
assert(Offset <= (int)StatepointCS.arg_size());
|
||||
return StatepointCS.arg_begin() + Offset;
|
||||
}
|
||||
|
||||
/// 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() {
|
||||
Value *NumVMSArgs = *call_args_end();
|
||||
Value *NumVMSArgs = *vm_state_begin();
|
||||
return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
|
||||
}
|
||||
|
||||
typename CallSiteTy::arg_iterator vm_state_begin() { return call_args_end(); }
|
||||
typename CallSiteTy::arg_iterator vm_state_begin() {
|
||||
return gc_transition_args_end();
|
||||
}
|
||||
typename CallSiteTy::arg_iterator vm_state_end() {
|
||||
int Offset = CallArgsBeginPos + getNumCallArgs() + 1 + getNumTotalVMSArgs();
|
||||
int Offset = (gc_transition_args_end() + 1 + getNumTotalVMSArgs()) -
|
||||
StatepointCS.arg_begin();
|
||||
assert(Offset <= (int)StatepointCS.arg_size());
|
||||
return StatepointCS.arg_begin() + Offset;
|
||||
}
|
||||
@@ -152,6 +191,8 @@ public:
|
||||
// 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();
|
||||
|
||||
Reference in New Issue
Block a user