diff options
Diffstat (limited to 'test/Verifier')
34 files changed, 435 insertions, 83 deletions
diff --git a/test/Verifier/alias.ll b/test/Verifier/alias.ll index dd04ae05f6341..1847c0d4214ed 100644 --- a/test/Verifier/alias.ll +++ b/test/Verifier/alias.ll @@ -2,18 +2,24 @@ declare void @f() -@fa = alias void ()* @f +@fa = alias void (), void ()* @f ; CHECK: Alias must point to a definition ; CHECK-NEXT: @fa @g = external global i32 -@ga = alias i32* @g +@ga = alias i32, i32* @g ; CHECK: Alias must point to a definition ; CHECK-NEXT: @ga +define available_externally void @f2() { + ret void +} +@fa2 = alias void(), void()* @f2 +; CHECK: Alias must point to a definition +; CHECK-NEXT: @fa2 -@test2_a = alias i32* @test2_b -@test2_b = alias i32* @test2_a +@test2_a = alias i32, i32* @test2_b +@test2_b = alias i32, i32* @test2_a ; CHECK: Aliases cannot form a cycle ; CHECK-NEXT: i32* @test2_a ; CHECK-NEXT: Aliases cannot form a cycle @@ -21,7 +27,7 @@ declare void @f() @test3_a = global i32 42 -@test3_b = weak alias i32* @test3_a -@test3_c = alias i32* @test3_b +@test3_b = weak alias i32, i32* @test3_a +@test3_c = alias i32, i32* @test3_b ; CHECK: Alias cannot point to a weak alias ; CHECK-NEXT: i32* @test3_c diff --git a/test/Verifier/align-md.ll b/test/Verifier/align-md.ll new file mode 100644 index 0000000000000..2de489ec21ebf --- /dev/null +++ b/test/Verifier/align-md.ll @@ -0,0 +1,59 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +declare i8* @foo() + +define void @f1() { +entry: + call i8* @foo(), !align !{i64 2} + ret void +} +; CHECK: align applies only to load instructions +; CHECK-NEXT: call i8* @foo() + +define i8 @f2(i8* %x) { +entry: + %y = load i8, i8* %x, !align !{i64 2} + ret i8 %y +} +; CHECK: align applies only to pointer types +; CHECK-NEXT: load i8, i8* %x + +define i8* @f3(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{} + ret i8* %y +} +; CHECK: align takes one operand +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f4(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{!"str"} + ret i8* %y +} +; CHECK: align metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f5(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{i32 2} + ret i8* %y +} +; CHECK: align metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f6(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{i64 3} + ret i8* %y +} +; CHECK: align metadata value must be a power of 2! +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f7(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{i64 1073741824} + ret i8* %y +} +; CHECK: alignment is larger that implementation defined limit +; CHECK-NEXT: load i8*, i8** %x
\ No newline at end of file diff --git a/test/Verifier/atomics.ll b/test/Verifier/atomics.ll new file mode 100644 index 0000000000000..e49a0eb7beb26 --- /dev/null +++ b/test/Verifier/atomics.ll @@ -0,0 +1,14 @@ +; RUN: not opt -verify < %s 2>&1 | FileCheck %s + +; CHECK: atomic store operand must have integer, pointer, or floating point type! +; CHECK: atomic load operand must have integer, pointer, or floating point type! + +define void @foo(x86_mmx* %P, x86_mmx %v) { + store atomic x86_mmx %v, x86_mmx* %P unordered, align 8 + ret void +} + +define x86_mmx @bar(x86_mmx* %P) { + %v = load atomic x86_mmx, x86_mmx* %P unordered, align 8 + ret x86_mmx %v +} diff --git a/test/Verifier/bitcast-alias-address-space.ll b/test/Verifier/bitcast-alias-address-space.ll index d9794d9e338a8..d5f2266aa6190 100644 --- a/test/Verifier/bitcast-alias-address-space.ll +++ b/test/Verifier/bitcast-alias-address-space.ll @@ -7,4 +7,4 @@ target datalayout = "e-p:32:32:32-p1:16:16:16-p2:32:32:32-i1:8:32-i8:8:32-i16:16 @data = addrspace(2) global i32 27 -@illegal_alias_data = alias bitcast (i32 addrspace(2)* @data to i32 addrspace(1)*) +@illegal_alias_data = alias i32, bitcast (i32 addrspace(2)* @data to i32 addrspace(1)*) diff --git a/test/Verifier/dbg-null-retained-type.ll b/test/Verifier/dbg-null-retained-type.ll new file mode 100644 index 0000000000000..f0368c8c48773 --- /dev/null +++ b/test/Verifier/dbg-null-retained-type.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as -disable-output <%s 2>&1 | FileCheck %s +; CHECK: assembly parsed, but does not verify +; CHECK-NEXT: invalid retained type + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!llvm.dbg.cu = !{!1} +!1 = distinct !DICompileUnit(file: !2, language: DW_LANG_C99, retainedTypes: !3) +!2 = !DIFile(filename: "file.c", directory: "/path/to/dir") +!3 = !{null} diff --git a/test/Verifier/dbg-typerefs.ll b/test/Verifier/dbg-typerefs.ll index dc50fce0715c6..2370f8b64e5b6 100644 --- a/test/Verifier/dbg-typerefs.ll +++ b/test/Verifier/dbg-typerefs.ll @@ -14,7 +14,7 @@ ; Add a minimal compile unit to resolve some of the type references. !llvm.dbg.cu = !{!5} -!5 = !DICompileUnit(file: !6, language: DW_LANG_C99, retainedTypes: !7) +!5 = distinct !DICompileUnit(file: !6, language: DW_LANG_C99, retainedTypes: !7) !6 = !DIFile(filename: "file.c", directory: "/path/to/dir") !7 = !{!8, !9} !8 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "1.good") diff --git a/test/Verifier/dbg.ll b/test/Verifier/dbg.ll index 395806b1299aa..d5728a4e82729 100644 --- a/test/Verifier/dbg.ll +++ b/test/Verifier/dbg.ll @@ -2,7 +2,7 @@ define void @foo() { entry: - br label %exit, !dbg !DILocation(scope: !DISubprogram(), inlinedAt: !{}) + br label %exit, !dbg !DILocation(scope: !1, inlinedAt: !{}) ; CHECK: inlined-at should be a location ; CHECK-NEXT: !{{[0-9]+}} = !DILocation(line: 0, scope: !{{[0-9]+}}, inlinedAt: ![[IA:[0-9]+]]) ; CHECK-NEXT: ![[IA]] = !{} @@ -16,3 +16,4 @@ exit: !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DISubprogram() diff --git a/test/Verifier/dereferenceable-md.ll b/test/Verifier/dereferenceable-md.ll new file mode 100644 index 0000000000000..94c89c3320229 --- /dev/null +++ b/test/Verifier/dereferenceable-md.ll @@ -0,0 +1,86 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +declare i8* @foo() + +define void @f1() { +entry: + call i8* @foo(), !dereferenceable !{i64 2} + ret void +} +; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes +; CHECK-NEXT: call i8* @foo() + +define void @f2() { +entry: + call i8* @foo(), !dereferenceable_or_null !{i64 2} + ret void +} +; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes +; CHECK-NEXT: call i8* @foo() + +define i8 @f3(i8* %x) { +entry: + %y = load i8, i8* %x, !dereferenceable !{i64 2} + ret i8 %y +} +; CHECK: dereferenceable, dereferenceable_or_null apply only to pointer types +; CHECK-NEXT: load i8, i8* %x + +define i8 @f4(i8* %x) { +entry: + %y = load i8, i8* %x, !dereferenceable_or_null !{i64 2} + ret i8 %y +} +; CHECK: dereferenceable, dereferenceable_or_null apply only to pointer types +; CHECK-NEXT: load i8, i8* %x + +define i8* @f5(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable !{} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null take one operand +; CHECK-NEXT: load i8*, i8** %x + + +define i8* @f6(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable_or_null !{} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null take one operand +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f7(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable !{!"str"} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x + + +define i8* @f8(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable_or_null !{!"str"} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x + +define i8* @f9(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable !{i32 2} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x + + +define i8* @f10(i8** %x) { +entry: + %y = load i8*, i8** %x, !dereferenceable_or_null !{i32 2} + ret i8* %y +} +; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64! +; CHECK-NEXT: load i8*, i8** %x
\ No newline at end of file diff --git a/test/Verifier/func-dbg.ll b/test/Verifier/func-dbg.ll new file mode 100644 index 0000000000000..e56de94d18c9e --- /dev/null +++ b/test/Verifier/func-dbg.ll @@ -0,0 +1,25 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +define i32 @foo() !dbg !4 { +entry: + ret i32 0, !dbg !6 +} + +define i32 @bar() !dbg !5 { +entry: +; CHECK: !dbg attachment points at wrong subprogram for function + ret i32 0, !dbg !6 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7, !8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: 0, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) +!1 = !DIFile(filename: "dwarf-test.c", directory: "test") +!2 = !{} +!3 = !{!4, !5} +!4 = distinct !DISubprogram(name: "foo", scope: !0, isDefinition: true) +!5 = distinct !DISubprogram(name: "bar", scope: !0, isDefinition: true) +!6 = !DILocation(line: 7, scope: !4) +!7 = !{i32 2, !"Dwarf Version", i32 3} +!8 = !{i32 1, !"Debug Info Version", i32 3} diff --git a/test/Verifier/gc_relocate_addrspace.ll b/test/Verifier/gc_relocate_addrspace.ll index ddc1b230a8c21..ccf1fbbe95ca1 100644 --- a/test/Verifier/gc_relocate_addrspace.ll +++ b/test/Verifier/gc_relocate_addrspace.ll @@ -3,21 +3,21 @@ ; address space with the relocated value. ; CHECK: gc.relocate: relocating a pointer shouldn't change its address space -; CHECK-NEXT: %obj.relocated = call coldcc i8* @llvm.experimental.gc.relocate.p0i8(i32 %safepoint_token, i32 7, i32 7) ; +; CHECK-NEXT: %obj.relocated = call coldcc i8* @llvm.experimental.gc.relocate.p0i8(token %safepoint_token, i32 7, i32 7) ; declare void @foo() ; Function Attrs: nounwind -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) #0 +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) #0 define void @test1(i64 addrspace(1)* %obj) gc "statepoint-example" { entry: - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj) - %obj.relocated = call coldcc i8* @llvm.experimental.gc.relocate.p0i8(i32 %safepoint_token, i32 7, i32 7) ; (%obj, %obj) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj) + %obj.relocated = call coldcc i8* @llvm.experimental.gc.relocate.p0i8(token %safepoint_token, i32 7, i32 7) ; (%obj, %obj) ret void } ; Function Attrs: nounwind -declare i8* @llvm.experimental.gc.relocate.p0i8(i32, i32, i32) #0 +declare i8* @llvm.experimental.gc.relocate.p0i8(token, i32, i32) #0 attributes #0 = { nounwind } diff --git a/test/Verifier/gc_relocate_operand.ll b/test/Verifier/gc_relocate_operand.ll index c28b8d870365c..f7c919ec1e932 100644 --- a/test/Verifier/gc_relocate_operand.ll +++ b/test/Verifier/gc_relocate_operand.ll @@ -5,17 +5,17 @@ declare void @foo() -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) define void @test1(i64 %obj) gc "statepoint-example" { entry: - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i64 %obj) - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 7, i32 7) ; (%obj, %obj) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i64 %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 7, i32 7) ; (%obj, %obj) ret void } ; Function Attrs: nounwind -declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32, i32, i32) #0 +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) #0 attributes #0 = { nounwind } diff --git a/test/Verifier/gc_relocate_return.ll b/test/Verifier/gc_relocate_return.ll index 3957d4c0cec85..77207f6c47b25 100644 --- a/test/Verifier/gc_relocate_return.ll +++ b/test/Verifier/gc_relocate_return.ll @@ -6,17 +6,17 @@ declare void @foo() -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) define void @test1(<2 x i32 addrspace(1)*> addrspace(1)* %obj) gc "statepoint-example" { entry: - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, <2 x i32 addrspace(1)*> addrspace(1)* %obj) - %obj.relocated = call coldcc i8 @llvm.experimental.gc.relocate.i8(i32 %safepoint_token, i32 7, i32 7) ; (%obj, %obj) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, <2 x i32 addrspace(1)*> addrspace(1)* %obj) + %obj.relocated = call coldcc i8 @llvm.experimental.gc.relocate.i8(token %safepoint_token, i32 7, i32 7) ; (%obj, %obj) ret void } ; Function Attrs: nounwind -declare i8 @llvm.experimental.gc.relocate.i8(i32, i32, i32) #0 +declare i8 @llvm.experimental.gc.relocate.i8(token, i32, i32) #0 attributes #0 = { nounwind } diff --git a/test/Verifier/invalid-eh.ll b/test/Verifier/invalid-eh.ll new file mode 100644 index 0000000000000..906b24a15c30a --- /dev/null +++ b/test/Verifier/invalid-eh.ll @@ -0,0 +1,38 @@ +; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s +; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s +; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s +; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s + +;T1: define void @f() { +;T1: entry: +;T1: catchret from undef to label %next +;T1: ; CHECK1: CatchReturnInst needs to be provided a CatchPad +;T1: next: +;T1: unreachable +;T1: } + +;T2: define void @f() { +;T2: entry: +;T2: %x = cleanuppad within none [] +;T2: ; catchret's first operand's operator must be catchpad +;T2: catchret from %x to label %entry +;T2: ; CHECK2: CatchReturnInst needs to be provided a CatchPad +;T2: } + +;T3: define void @f() { +;T3: entry: +;T3: cleanupret from undef unwind label %next +;T3: ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad +;T3: next: +;T3: unreachable +;T3: } + +;T4: define void @f() { +;T4: entry: +;T4: %cs = catchswitch within none [label %next] unwind to caller +;T4: next: +;T4: %x = catchpad within %cs [] +;T4: ; cleanupret first operand's operator must be cleanuppad +;T4: cleanupret from %x unwind to caller +;T4: ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad +;T4: } diff --git a/test/Verifier/invalid-patchable-statepoint.ll b/test/Verifier/invalid-patchable-statepoint.ll deleted file mode 100644 index 4783fa57f8fab..0000000000000 --- a/test/Verifier/invalid-patchable-statepoint.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: not opt -verify 2>&1 < %s | FileCheck %s - -; CHECK: gc.statepoint must have null as call target if number of patchable bytes is non zero - -define i1 @invalid_patchable_statepoint() gc "statepoint-example" { -entry: - %safepoint_token = tail call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 3, i1 ()* @func, i32 0, i32 0, i32 0, i32 0) - %call1 = call i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) - ret i1 %call1 -} - -declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) -declare i1 @llvm.experimental.gc.result.i1(i32) -declare i1 @func() diff --git a/test/Verifier/invalid-statepoint.ll b/test/Verifier/invalid-statepoint.ll index 6c3525a16df53..6b4bc087b3e0c 100644 --- a/test/Verifier/invalid-statepoint.ll +++ b/test/Verifier/invalid-statepoint.ll @@ -5,15 +5,15 @@ declare zeroext i1 @return0i1() ; Function Attrs: nounwind -declare i32 @llvm.experimental.gc.statepoint.p0f0i1f(i64, i32, i1 ()*, i32, i32, ...) #0 +declare token @llvm.experimental.gc.statepoint.p0f0i1f(i64, i32, i1 ()*, i32, i32, ...) #0 ; Function Attrs: nounwind -declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) #0 +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #0 define i32 addrspace(1)* @0(i32 addrspace(1)* %dparam) { %a00 = load i32, i32 addrspace(1)* %dparam - %to0 = call i32 (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f0i1f(i64 0, i32 0, i1 ()* @return0i1, i32 9, i32 0, i2 0, i32 addrspace(1)* %dparam) - %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %to0, i32 2, i32 6) + %to0 = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f0i1f(i64 0, i32 0, i1 ()* @return0i1, i32 9, i32 0, i2 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %to0, i32 2, i32 6) ret i32 addrspace(1)* %relocate } diff --git a/test/Verifier/invalid-statepoint2.ll b/test/Verifier/invalid-statepoint2.ll index c8b453c31e694..10bcd4f4f318f 100644 --- a/test/Verifier/invalid-statepoint2.ll +++ b/test/Verifier/invalid-statepoint2.ll @@ -3,16 +3,16 @@ ; CHECK: gc.statepoint: number of deoptimization arguments must be a constant integer declare void @use(...) -declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32, i32, i32) -declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32, i32, i32) -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) +declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) declare i32 @"personality_function"() ;; Basic usage define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg, i32 %val) gc "statepoint-example" { entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 12, i32 13) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) ret i64 addrspace(1)* %reloc } diff --git a/test/Verifier/invoke.ll b/test/Verifier/invoke.ll index b56b72f84b9eb..8fa9923c0cb85 100644 --- a/test/Verifier/invoke.ll +++ b/test/Verifier/invoke.ll @@ -2,7 +2,7 @@ ; PR1042 define i32 @foo() { -; CHECK: The unwind destination does not have a landingpad instruction +; CHECK: The unwind destination does not have an exception handling instruction %A = invoke i32 @foo( ) to label %L unwind label %L ; <i32> [#uses=1] L: ; preds = %0, %0 @@ -18,7 +18,7 @@ L1: ; preds = %0 L2: ; preds = %0 br label %L L: ; preds = %L2, %L1, %L1 -; CHECK: The unwind destination does not have a landingpad instruction +; CHECK: The unwind destination does not have an exception handling instruction ret i32 %A } diff --git a/test/Verifier/llvm.dbg.declare-address.ll b/test/Verifier/llvm.dbg.declare-address.ll index ba132ad53465f..90cf72aea6819 100644 --- a/test/Verifier/llvm.dbg.declare-address.ll +++ b/test/Verifier/llvm.dbg.declare-address.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.declare(metadata !"", metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !1) + call void @llvm.dbg.declare(metadata !"", metadata !DILocalVariable(scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !1) ret void } @@ -14,4 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/llvm.dbg.declare-expression.ll b/test/Verifier/llvm.dbg.declare-expression.ll index 4c1bd65230a97..54ee1f750d4ab 100644 --- a/test/Verifier/llvm.dbg.declare-expression.ll +++ b/test/Verifier/llvm.dbg.declare-expression.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.declare(metadata i32* %s, metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !"") + call void @llvm.dbg.declare(metadata i32* %s, metadata !DILocalVariable(scope: !1), metadata !"") ret void } @@ -14,4 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/llvm.dbg.declare-variable.ll b/test/Verifier/llvm.dbg.declare-variable.ll index deef50fd717d6..6f415b7c1fa03 100644 --- a/test/Verifier/llvm.dbg.declare-variable.ll +++ b/test/Verifier/llvm.dbg.declare-variable.ll @@ -14,4 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll b/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll index 717794b4274b0..9612643aa9d37 100644 --- a/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll +++ b/test/Verifier/llvm.dbg.intrinsic-dbg-attachment.ll @@ -4,7 +4,7 @@ entry: call void @llvm.dbg.value( metadata i8* undef, i64 0, - metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !DILocalVariable(scope: !1), metadata !DIExpression()) ; CHECK-LABEL: llvm.dbg.value intrinsic requires a !dbg attachment ; CHECK-NEXT: call void @llvm.dbg.value({{.*}}) @@ -13,7 +13,7 @@ entry: call void @llvm.dbg.declare( metadata i8* undef, - metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !DILocalVariable(scope: !1), metadata !DIExpression()) ; CHECK-LABEL: llvm.dbg.declare intrinsic requires a !dbg attachment ; CHECK-NEXT: call void @llvm.dbg.declare({{.*}}) @@ -23,7 +23,7 @@ entry: call void @llvm.dbg.value( metadata i8* undef, i64 0, - metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !DILocalVariable(scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !2) ; CHECK-LABEL: mismatched subprogram between llvm.dbg.value variable and !dbg attachment @@ -31,13 +31,13 @@ entry: ; CHECK-NEXT: label %entry ; CHECK-NEXT: void ()* @foo ; CHECK-NEXT: ![[VAR]] = !DILocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] -; CHECK-NEXT: ![[VARSP]] = !DISubprogram( +; CHECK-NEXT: ![[VARSP]] = distinct !DISubprogram( ; CHECK-NEXT: ![[LOC]] = !DILocation({{.*}}scope: ![[LOCSP:[0-9]+]] -; CHECK-NEXT: ![[LOCSP]] = !DISubprogram( +; CHECK-NEXT: ![[LOCSP]] = distinct !DISubprogram( call void @llvm.dbg.declare( metadata i8* undef, - metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), + metadata !DILocalVariable(scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !2) ; CHECK-LABEL: mismatched subprogram between llvm.dbg.declare variable and !dbg attachment @@ -45,9 +45,9 @@ entry: ; CHECK-NEXT: label %entry ; CHECK-NEXT: void ()* @foo ; CHECK-NEXT: ![[VAR]] = !DILocalVariable({{.*}}scope: ![[VARSP:[0-9]+]] -; CHECK-NEXT: ![[VARSP]] = !DISubprogram( +; CHECK-NEXT: ![[VARSP]] = distinct !DISubprogram( ; CHECK-NEXT: ![[LOC]] = !DILocation({{.*}}scope: ![[LOCSP:[0-9]+]] -; CHECK-NEXT: ![[LOCSP]] = !DISubprogram( +; CHECK-NEXT: ![[LOCSP]] = distinct !DISubprogram( ret void } @@ -57,5 +57,5 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram(name: "foo") -!2 = !DISubprogram(name: "bar") +!1 = distinct !DISubprogram(name: "foo") +!2 = distinct !DISubprogram(name: "bar") diff --git a/test/Verifier/llvm.dbg.value-expression.ll b/test/Verifier/llvm.dbg.value-expression.ll index 78a7c50f233d5..dd3c29f91073e 100644 --- a/test/Verifier/llvm.dbg.value-expression.ll +++ b/test/Verifier/llvm.dbg.value-expression.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !""), !dbg !DILocation(scope: !1) + call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !DILocalVariable(scope: !1), metadata !""), !dbg !DILocation(scope: !1) ret void } @@ -14,4 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/llvm.dbg.value-value.ll b/test/Verifier/llvm.dbg.value-value.ll index 1acb5f8132faf..e1d02de484c63 100644 --- a/test/Verifier/llvm.dbg.value-value.ll +++ b/test/Verifier/llvm.dbg.value-value.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata !"", i64 0, metadata !DILocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !1) + call void @llvm.dbg.value(metadata !"", i64 0, metadata !DILocalVariable(scope: !1), metadata !DIExpression()), !dbg !DILocation(scope: !1) ret void } @@ -14,4 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/llvm.dbg.value-variable.ll b/test/Verifier/llvm.dbg.value-variable.ll index 66329f9fdaa73..745f7ada58738 100644 --- a/test/Verifier/llvm.dbg.value-variable.ll +++ b/test/Verifier/llvm.dbg.value-variable.ll @@ -14,4 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram() +!1 = distinct !DISubprogram() diff --git a/test/Verifier/metadata-function-dbg.ll b/test/Verifier/metadata-function-dbg.ll new file mode 100644 index 0000000000000..2a6fd8bbb48e4 --- /dev/null +++ b/test/Verifier/metadata-function-dbg.ll @@ -0,0 +1,23 @@ +; RUN: not llvm-as %s -disable-output 2>&1 | FileCheck %s + +define void @foo() !dbg !4 !dbg !4 { + unreachable +} + +; CHECK-NOT: !dbg +; CHECK: function !dbg attachment must be a subprogram +; CHECK-NEXT: void ()* @bar +; CHECK-NEXT: !{{[0-9]+}} = !{} +define void @bar() !dbg !6 { + unreachable +} + +!llvm.module.flags = !{!0} +!0 = !{i32 2, !"Debug Info Version", i32 3} + +!llvm.dbg.cu = !{!1} +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, subprograms: !3) +!2 = !DIFile(filename: "t.c", directory: "/path/to/dir") +!3 = !{!4} +!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !2) +!6 = !{} diff --git a/test/Verifier/operand-bundles.ll b/test/Verifier/operand-bundles.ll new file mode 100644 index 0000000000000..d822568a04455 --- /dev/null +++ b/test/Verifier/operand-bundles.ll @@ -0,0 +1,49 @@ +; RUN: not opt -verify < %s 2>&1 | FileCheck %s + +; Operand bundles uses are like regular uses, and need to be dominated +; by their defs. + +declare void @g() + +define void @f0(i32* %ptr) { +; CHECK: Instruction does not dominate all uses! +; CHECK-NEXT: %x = add i32 42, 1 +; CHECK-NEXT: call void @g() [ "foo"(i32 42, i64 100, i32 %x), "bar"(float 0.000000e+00, i64 100, i32 %l) ] + + entry: + %l = load i32, i32* %ptr + call void @g() [ "foo"(i32 42, i64 100, i32 %x), "bar"(float 0.0, i64 100, i32 %l) ] + %x = add i32 42, 1 + ret void +} + +define void @f1(i32* %ptr) personality i8 3 { +; CHECK: Instruction does not dominate all uses! +; CHECK-NEXT: %x = add i32 42, 1 +; CHECK-NEXT: invoke void @g() [ "foo"(i32 42, i64 100, i32 %x), "bar"(float 0.000000e+00, i64 100, i32 %l) ] + + entry: + %l = load i32, i32* %ptr + invoke void @g() [ "foo"(i32 42, i64 100, i32 %x), "bar"(float 0.0, i64 100, i32 %l) ] to label %normal unwind label %exception + +exception: + %cleanup = landingpad i8 cleanup + br label %normal + +normal: + %x = add i32 42, 1 + ret void +} + +define void @f_deopt(i32* %ptr) { +; CHECK: Multiple deopt operand bundles +; CHECK-NEXT: call void @g() [ "deopt"(i32 42, i64 100, i32 %x), "deopt"(float 0.000000e+00, i64 100, i32 %l) ] +; CHECK-NOT: call void @g() [ "deopt"(i32 42, i64 120, i32 %x) ] + + entry: + %l = load i32, i32* %ptr + call void @g() [ "deopt"(i32 42, i64 100, i32 %x), "deopt"(float 0.0, i64 100, i32 %l) ] + call void @g() [ "deopt"(i32 42, i64 120) ] ;; The verifier should not complain about this one + %x = add i32 42, 1 + ret void +} diff --git a/test/Verifier/statepoint.ll b/test/Verifier/statepoint.ll index 2807620f79eaa..c07a85b9bd368 100644 --- a/test/Verifier/statepoint.ll +++ b/test/Verifier/statepoint.ll @@ -1,20 +1,20 @@ ; RUN: opt -S %s -verify | FileCheck %s declare void @use(...) -declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32, i32, i32) -declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32, i32, i32) -declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) +declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32) +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) declare i32 @"personality_function"() ;; Basic usage define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" { entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 12, i32 13) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) ;; It is perfectly legal to relocate the same value multiple times... - %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 12, i32 13) - %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 13, i32 12) + %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) + %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 13, i32 12) ret i64 addrspace(1)* %reloc ; CHECK-LABEL: test1 ; CHECK: statepoint @@ -39,8 +39,8 @@ notequal: ret void equal: - %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 12, i32 13) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) call void undef(i64 addrspace(1)* %reloc) ret void ; CHECK-LABEL: test2 @@ -57,7 +57,7 @@ define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc entry: ; CHECK-LABEL: entry ; CHECK: statepoint - %0 = invoke i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) + %0 = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) to label %normal_dest unwind label %exceptional_return normal_dest: @@ -65,18 +65,17 @@ normal_dest: ; CHECK: gc.relocate ; CHECK: gc.relocate ; CHECK: ret - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 12, i32 12) - %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 12, i32 12) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) + %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) ret i8 addrspace(1)* %obj.relocated exceptional_return: ; CHECK-LABEL: exceptional_return ; CHECK: gc.relocate ; CHECK: gc.relocate - %landing_pad = landingpad { i8*, i32 } + %landing_pad = landingpad token cleanup - %relocate_token = extractvalue { i8*, i32 } %landing_pad, 1 - %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 12, i32 12) - %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 12, i32 12) + %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) + %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) ret i8 addrspace(1)* %obj1.relocated1 } diff --git a/test/Verifier/token1.ll b/test/Verifier/token1.ll new file mode 100644 index 0000000000000..ac7ff30948ea3 --- /dev/null +++ b/test/Verifier/token1.ll @@ -0,0 +1,11 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(token %A, token %B) { +entry: + br label %bb + +bb: + %phi = phi token [ %A, %bb ], [ %B, %entry] +; CHECK: PHI nodes cannot have token type! + br label %bb +} diff --git a/test/Verifier/token2.ll b/test/Verifier/token2.ll new file mode 100644 index 0000000000000..b58079de770d5 --- /dev/null +++ b/test/Verifier/token2.ll @@ -0,0 +1,11 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(token %A, token %B) { +entry: + br label %bb + +bb: + %sel = select i1 undef, token %A, token %B +; CHECK: select values cannot have token type + br label %bb +} diff --git a/test/Verifier/token3.ll b/test/Verifier/token3.ll new file mode 100644 index 0000000000000..2cce6b83e7fdd --- /dev/null +++ b/test/Verifier/token3.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(token %A, token %B) { +entry: + alloca token +; CHECK: invalid type for alloca + ret void +} diff --git a/test/Verifier/token4.ll b/test/Verifier/token4.ll new file mode 100644 index 0000000000000..87a8b14efa005 --- /dev/null +++ b/test/Verifier/token4.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +@GV = external global token +; CHECK: invalid type for global variable diff --git a/test/Verifier/token5.ll b/test/Verifier/token5.ll new file mode 100644 index 0000000000000..6fc1b045375f4 --- /dev/null +++ b/test/Verifier/token5.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f(token %A) { +entry: + ret void +} +; CHECK: Function takes token but isn't an intrinsic diff --git a/test/Verifier/token6.ll b/test/Verifier/token6.ll new file mode 100644 index 0000000000000..9614b91db7377 --- /dev/null +++ b/test/Verifier/token6.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define token @f() { +entry: + ret token undef +} +; CHECK: Functions returns a token but isn't an intrinsic diff --git a/test/Verifier/token7.ll b/test/Verifier/token7.ll new file mode 100644 index 0000000000000..939878cc4275a --- /dev/null +++ b/test/Verifier/token7.ll @@ -0,0 +1,8 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @f() { +entry: + call token () undef () + ret void +} +; CHECK: Return type cannot be token for indirect call! |
