mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Require a GC strategy be specified for functions which use gc.statepoint
This was discussed a while back and I left it optional for migration. Since it's been far more than the 'week or two' that was discussed, time to actually make this manditory. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233357 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
28ffcd3f1e
commit
76acab3fc7
@ -442,27 +442,25 @@ static void lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
|
||||
// heap. This is basically just here to help catch errors during statepoint
|
||||
// insertion. TODO: This should actually be in the Verifier, but we can't get
|
||||
// to the GCStrategy from there (yet).
|
||||
if (Builder.GFI) {
|
||||
GCStrategy &S = Builder.GFI->getStrategy();
|
||||
for (const Value *V : Bases) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() &&
|
||||
"non gc managed base pointer found in statepoint");
|
||||
}
|
||||
GCStrategy &S = Builder.GFI->getStrategy();
|
||||
for (const Value *V : Bases) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() &&
|
||||
"non gc managed base pointer found in statepoint");
|
||||
}
|
||||
for (const Value *V : Ptrs) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() &&
|
||||
"non gc managed derived pointer found in statepoint");
|
||||
}
|
||||
}
|
||||
for (const Value *V : Ptrs) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() &&
|
||||
"non gc managed derived pointer found in statepoint");
|
||||
}
|
||||
for (const Value *V : Relocations) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() && "non gc managed pointer relocated");
|
||||
}
|
||||
}
|
||||
for (const Value *V : Relocations) {
|
||||
auto Opt = S.isGCManagedPointer(V);
|
||||
if (Opt.hasValue()) {
|
||||
assert(Opt.getValue() && "non gc managed pointer relocated");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -581,10 +579,8 @@ SelectionDAGBuilder::LowerStatepoint(ImmutableStatepoint ISP,
|
||||
// TODO: This if should become an assert. For now, we allow the GCStrategy
|
||||
// to be optional for backwards compatibility. This will only last a short
|
||||
// period (i.e. a couple of weeks).
|
||||
if (GFI) {
|
||||
assert(GFI->getStrategy().useStatepoints() &&
|
||||
"GCStrategy does not expect to encounter statepoints");
|
||||
}
|
||||
assert(GFI->getStrategy().useStatepoints() &&
|
||||
"GCStrategy does not expect to encounter statepoints");
|
||||
#endif
|
||||
|
||||
// Lower statepoint vmstate and gcstate arguments
|
||||
|
@ -2926,6 +2926,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
case Intrinsic::experimental_gc_statepoint:
|
||||
Assert(!CI.isInlineAsm(),
|
||||
"gc.statepoint support for inline assembly unimplemented", &CI);
|
||||
Assert(CI.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", &CI);
|
||||
|
||||
VerifyStatepoint(ImmutableCallSite(&CI));
|
||||
break;
|
||||
@ -2933,6 +2935,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
case Intrinsic::experimental_gc_result_float:
|
||||
case Intrinsic::experimental_gc_result_ptr:
|
||||
case Intrinsic::experimental_gc_result: {
|
||||
Assert(CI.getParent()->getParent()->hasGC(),
|
||||
"Enclosing function does not use GC.", &CI);
|
||||
// Are we tied to a statepoint properly?
|
||||
CallSite StatepointCS(CI.getArgOperand(0));
|
||||
const Function *StatepointFn =
|
||||
|
@ -9,7 +9,7 @@ declare zeroext i1 @return_i1()
|
||||
|
||||
@globalstr = global [6 x i8] c"hello\00"
|
||||
|
||||
define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) {
|
||||
define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" {
|
||||
; CHECK: The following are dereferenceable:
|
||||
; CHECK: %globalptr
|
||||
; CHECK: %alloca
|
||||
|
@ -12,28 +12,28 @@
|
||||
; will serve the purpose.
|
||||
|
||||
; function and integer
|
||||
define i32* @test_iAny(i32* %v) {
|
||||
define i32* @test_iAny(i32* %v) gc "statepoint-example" {
|
||||
%tok = call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %v)
|
||||
%v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
|
||||
ret i32* %v-new
|
||||
}
|
||||
|
||||
; float
|
||||
define float* @test_fAny(float* %v) {
|
||||
define float* @test_fAny(float* %v) gc "statepoint-example" {
|
||||
%tok = call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, float* %v)
|
||||
%v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 4, i32 4)
|
||||
ret float* %v-new
|
||||
}
|
||||
|
||||
; array of integers
|
||||
define [3 x i32]* @test_aAny([3 x i32]* %v) {
|
||||
define [3 x i32]* @test_aAny([3 x i32]* %v) gc "statepoint-example" {
|
||||
%tok = call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %v)
|
||||
%v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
|
||||
ret [3 x i32]* %v-new
|
||||
}
|
||||
|
||||
; vector of integers
|
||||
define <3 x i32>* @test_vAny(<3 x i32>* %v) {
|
||||
define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" {
|
||||
%tok = call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, <3 x i32>* %v)
|
||||
%v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 4, i32 4)
|
||||
ret <3 x i32>* %v-new
|
||||
@ -42,7 +42,7 @@ define <3 x i32>* @test_vAny(<3 x i32>* %v) {
|
||||
%struct.test = type { i32, i1 }
|
||||
|
||||
; struct
|
||||
define %struct.test* @test_struct(%struct.test* %v) {
|
||||
define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" {
|
||||
%tok = call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, %struct.test* %v)
|
||||
%v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 4, i32 4)
|
||||
ret %struct.test* %v-new
|
||||
|
@ -6,7 +6,9 @@ declare i64 addrspace(1)* @"some_other_call"(i64 addrspace(1)*)
|
||||
|
||||
declare i32 @"personality_function"()
|
||||
|
||||
define i64 addrspace(1)* @test_result(i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) {
|
||||
define i64 addrspace(1)* @test_result(i64 addrspace(1)* %obj,
|
||||
i64 addrspace(1)* %obj1)
|
||||
gc "statepoint-example" {
|
||||
entry:
|
||||
; CHECK: .Ltmp{{[0-9]+}}:
|
||||
; CHECK: callq some_other_call
|
||||
|
@ -8,7 +8,7 @@ target triple = "x86_64-pc-linux-gnu"
|
||||
; of GC arguments differ, niave lowering code would insert loads and
|
||||
; stores to rearrange items on the stack. We need to make sure (for
|
||||
; performance) that this doesn't happen.
|
||||
define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 {
|
||||
define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" {
|
||||
; CHECK-LABEL: back_to_back_calls
|
||||
; The exact stores don't matter, but there need to be three stack slots created
|
||||
; CHECK: movq %rdx, 16(%rsp)
|
||||
@ -31,7 +31,7 @@ define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 a
|
||||
|
||||
; This test simply checks that minor changes in vm state don't prevent slots
|
||||
; being reused for gc values.
|
||||
define i32 @reserve_first(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 {
|
||||
define i32 @reserve_first(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) #1 gc "statepoint-example" {
|
||||
; CHECK-LABEL: reserve_first
|
||||
; The exact stores don't matter, but there need to be three stack slots created
|
||||
; CHECK: movq %rdx, 16(%rsp)
|
||||
|
@ -5,7 +5,7 @@ target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
declare zeroext i1 @return_i1()
|
||||
|
||||
define i32 @test_sor_basic(i32* %base) {
|
||||
define i32 @test_sor_basic(i32* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32* %base-new, i32 15
|
||||
entry:
|
||||
@ -17,7 +17,7 @@ entry:
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_two_derived(i32* %base) {
|
||||
define i32 @test_sor_two_derived(i32* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32* %base, i32 12
|
||||
; CHECK: getelementptr i32, i32* %base-new, i32 15
|
||||
@ -33,7 +33,7 @@ entry:
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_ooo(i32* %base) {
|
||||
define i32 @test_sor_ooo(i32* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32* %base-new, i32 15
|
||||
entry:
|
||||
@ -45,7 +45,7 @@ entry:
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_gep_smallint([3 x i32]* %base) {
|
||||
define i32 @test_sor_gep_smallint([3 x i32]* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 2
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 2
|
||||
entry:
|
||||
@ -57,7 +57,7 @@ entry:
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_gep_largeint([3 x i32]* %base) {
|
||||
define i32 @test_sor_gep_largeint([3 x i32]* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 21
|
||||
; CHECK-NOT: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 21
|
||||
entry:
|
||||
@ -69,7 +69,7 @@ entry:
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_noop(i32* %base) {
|
||||
define i32 @test_sor_noop(i32* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32* %base, i32 15
|
||||
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
|
||||
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
|
||||
|
@ -9,7 +9,7 @@ declare zeroext i1 @return_i1()
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
|
||||
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)
|
||||
|
||||
define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) {
|
||||
define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) gc "statepoint-example" {
|
||||
; Checks that a dereferenceabler pointer
|
||||
; CHECK-LABEL: @deref
|
||||
; CHECK: call dereferenceable(8)
|
||||
@ -18,4 +18,4 @@ entry:
|
||||
%tok = tail call i32 (i1 ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
|
||||
%relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4)
|
||||
ret i32 addrspace(1)* %relocate
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
declare void @func()
|
||||
|
||||
define i1 @test_negative(i32 addrspace(1)* %p) {
|
||||
define i1 @test_negative(i32 addrspace(1)* %p) gc "statepoint-example" {
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
|
||||
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
@ -16,7 +16,7 @@ entry:
|
||||
; CHECK: ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) {
|
||||
define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) gc "statepoint-example" {
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
|
||||
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
@ -26,7 +26,7 @@ entry:
|
||||
; CHECK: ret i1 false
|
||||
}
|
||||
|
||||
define i1 @test_null() {
|
||||
define i1 @test_null() gc "statepoint-example" {
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* null)
|
||||
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
@ -37,7 +37,7 @@ entry:
|
||||
; CHECK: ret i1 true
|
||||
}
|
||||
|
||||
define i1 @test_undef() {
|
||||
define i1 @test_undef() gc "statepoint-example" {
|
||||
entry:
|
||||
%safepoint_token = tail call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* undef)
|
||||
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
|
||||
|
@ -75,7 +75,7 @@ merge:
|
||||
}
|
||||
|
||||
; When run over a function which doesn't opt in, should do nothing!
|
||||
define i8 addrspace(1)* @test5(i8 addrspace(1)* %obj) {
|
||||
define i8 addrspace(1)* @test5(i8 addrspace(1)* %obj) gc "ocaml" {
|
||||
; CHECK-LABEL: @test5
|
||||
; CHECK-LABEL: entry:
|
||||
; CHECK-NEXT: gc.statepoint
|
||||
|
Loading…
Reference in New Issue
Block a user