mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-03 13:31:05 +00:00
Add invoke related functionality into StatepointSite classes.
Differential Revision: http://reviews.llvm.org/D7364 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229838 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
675d06d1d0
commit
589d13e8f5
@ -24,14 +24,17 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
bool isStatepoint(const ImmutableCallSite &CS);
|
class GCRelocateOperands;
|
||||||
bool isStatepoint(const Instruction *inst);
|
class ImmutableStatepoint;
|
||||||
bool isStatepoint(const Instruction &inst);
|
|
||||||
|
|
||||||
bool isGCRelocate(const Instruction *inst);
|
bool isStatepoint(const ImmutableCallSite &CS);
|
||||||
|
bool isStatepoint(const Value *inst);
|
||||||
|
bool isStatepoint(const Value &inst);
|
||||||
|
|
||||||
|
bool isGCRelocate(const Value *inst);
|
||||||
bool isGCRelocate(const ImmutableCallSite &CS);
|
bool isGCRelocate(const ImmutableCallSite &CS);
|
||||||
|
|
||||||
bool isGCResult(const Instruction *inst);
|
bool isGCResult(const Value *inst);
|
||||||
bool isGCResult(const ImmutableCallSite &CS);
|
bool isGCResult(const ImmutableCallSite &CS);
|
||||||
|
|
||||||
/// Analogous to CallSiteBase, this provides most of the actual
|
/// Analogous to CallSiteBase, this provides most of the actual
|
||||||
@ -127,6 +130,11 @@ class StatepointBase {
|
|||||||
return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
|
return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get list of all gc reloactes linked to this statepoint
|
||||||
|
/// May contain several relocations for the same base/derived pair.
|
||||||
|
/// For example this could happen due to relocations on unwinding
|
||||||
|
/// path of invoke.
|
||||||
|
std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/// Asserts if this statepoint is malformed. Common cases for failure
|
/// Asserts if this statepoint is malformed. Common cases for failure
|
||||||
@ -187,9 +195,39 @@ class GCRelocateOperands {
|
|||||||
assert(isGCRelocate(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get enclosed relocate intrinsic
|
||||||
|
ImmutableCallSite getUnderlyingCallSite() {
|
||||||
|
return RelocateCS;
|
||||||
|
}
|
||||||
|
|
||||||
/// The statepoint with which this gc.relocate is associated.
|
/// The statepoint with which this gc.relocate is associated.
|
||||||
const Instruction *statepoint() {
|
const Instruction *statepoint() {
|
||||||
return cast<Instruction>(RelocateCS.getArgument(0));
|
const Value *token = RelocateCS.getArgument(0);
|
||||||
|
|
||||||
|
// This takes care both of relocates for call statepoints and relocates
|
||||||
|
// on normal path of invoke statepoint.
|
||||||
|
if (!isa<ExtractValueInst>(token)) {
|
||||||
|
return cast<Instruction>(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This relocate is on exceptional path of an invoke statepoint
|
||||||
|
const BasicBlock *invokeBB =
|
||||||
|
cast<Instruction>(token)->getParent()->getUniquePredecessor();
|
||||||
|
|
||||||
|
assert(invokeBB && "safepoints should have unique landingpads");
|
||||||
|
assert(invokeBB->getTerminator() && "safepoint block should be well formed");
|
||||||
|
assert(isStatepoint(invokeBB->getTerminator()));
|
||||||
|
|
||||||
|
return invokeBB->getTerminator();
|
||||||
}
|
}
|
||||||
/// The index into the associate statepoint's argument list
|
/// The index into the associate statepoint's argument list
|
||||||
/// which contains the base pointer of the pointer whose
|
/// which contains the base pointer of the pointer whose
|
||||||
@ -211,5 +249,49 @@ class GCRelocateOperands {
|
|||||||
return *(CS.arg_begin() + derivedPtrIndex());
|
return *(CS.arg_begin() + derivedPtrIndex());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
|
||||||
|
std::vector<GCRelocateOperands>
|
||||||
|
StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
|
||||||
|
getRelocates(ImmutableStatepoint &IS) {
|
||||||
|
|
||||||
|
std::vector<GCRelocateOperands> res;
|
||||||
|
|
||||||
|
ImmutableCallSite StatepointCS = IS.getCallSite();
|
||||||
|
|
||||||
|
// Search for relocated pointers. Note that working backwards from the
|
||||||
|
// gc_relocates ensures that we only get pairs which are actually relocated
|
||||||
|
// and used after the statepoint.
|
||||||
|
for (const User *U : StatepointCS.getInstruction()->users()) {
|
||||||
|
if (isGCRelocate(U)) {
|
||||||
|
res.push_back(GCRelocateOperands(U));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StatepointCS.isInvoke()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to scan thorough exceptional relocations if it is invoke statepoint
|
||||||
|
LandingPadInst *LandingPad =
|
||||||
|
cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
|
||||||
|
|
||||||
|
// Search for extract value from landingpad instruction to which
|
||||||
|
// gc relocates will be attached
|
||||||
|
for (const User *LandingPadUser : LandingPad->users()) {
|
||||||
|
if (!isa<ExtractValueInst>(LandingPadUser)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// gc relocates should be attached to this extract value
|
||||||
|
for (const User *U : LandingPadUser->users()) {
|
||||||
|
if (isGCRelocate(U)) {
|
||||||
|
res.push_back(GCRelocateOperands(U));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,24 +20,34 @@ using namespace std;
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
bool llvm::isStatepoint(const ImmutableCallSite &CS) {
|
bool llvm::isStatepoint(const ImmutableCallSite &CS) {
|
||||||
|
if (!CS.getInstruction()) {
|
||||||
|
// This is not a call site
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const Function *F = CS.getCalledFunction();
|
const Function *F = CS.getCalledFunction();
|
||||||
return (F && F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint);
|
return (F && F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint);
|
||||||
}
|
}
|
||||||
bool llvm::isStatepoint(const Instruction *inst) {
|
bool llvm::isStatepoint(const Value *inst) {
|
||||||
if (isa<InvokeInst>(inst) || isa<CallInst>(inst)) {
|
if (isa<InvokeInst>(inst) || isa<CallInst>(inst)) {
|
||||||
ImmutableCallSite CS(inst);
|
ImmutableCallSite CS(inst);
|
||||||
return isStatepoint(CS);
|
return isStatepoint(CS);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool llvm::isStatepoint(const Instruction &inst) {
|
bool llvm::isStatepoint(const Value &inst) {
|
||||||
return isStatepoint(&inst);
|
return isStatepoint(&inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool llvm::isGCRelocate(const ImmutableCallSite &CS) {
|
bool llvm::isGCRelocate(const ImmutableCallSite &CS) {
|
||||||
|
if (!CS.getInstruction()) {
|
||||||
|
// This is not a call site
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return isGCRelocate(CS.getInstruction());
|
return isGCRelocate(CS.getInstruction());
|
||||||
}
|
}
|
||||||
bool llvm::isGCRelocate(const Instruction *inst) {
|
bool llvm::isGCRelocate(const Value *inst) {
|
||||||
if (const CallInst *call = dyn_cast<CallInst>(inst)) {
|
if (const CallInst *call = dyn_cast<CallInst>(inst)) {
|
||||||
if (const Function *F = call->getCalledFunction()) {
|
if (const Function *F = call->getCalledFunction()) {
|
||||||
return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
|
return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
|
||||||
@ -47,9 +57,14 @@ bool llvm::isGCRelocate(const Instruction *inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool llvm::isGCResult(const ImmutableCallSite &CS) {
|
bool llvm::isGCResult(const ImmutableCallSite &CS) {
|
||||||
|
if (!CS.getInstruction()) {
|
||||||
|
// This is not a call site
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return isGCResult(CS.getInstruction());
|
return isGCResult(CS.getInstruction());
|
||||||
}
|
}
|
||||||
bool llvm::isGCResult(const Instruction *inst) {
|
bool llvm::isGCResult(const Value *inst) {
|
||||||
if (const CallInst *call = dyn_cast<CallInst>(inst)) {
|
if (const CallInst *call = dyn_cast<CallInst>(inst)) {
|
||||||
if (Function *F = call->getCalledFunction()) {
|
if (Function *F = call->getCalledFunction()) {
|
||||||
return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int ||
|
return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int ||
|
||||||
|
Loading…
Reference in New Issue
Block a user