11//@ compile-flags: -Z annotate-moves=8 -Copt-level=0 -g
2+ //
3+ // This test verifies that function call and return instructions use the correct debug scopes
4+ // when passing/returning large values. The actual move/copy operations may be annotated,
5+ // but the CALL and RETURN instructions themselves should reference the source location,
6+ // NOT have an inlinedAt scope pointing to compiler_move/compiler_copy.
27
38#![ crate_type = "lib" ]
49
@@ -7,27 +12,103 @@ pub struct LargeStruct {
712 pub data : [ u64 ; 20 ] , // 160 bytes
813}
914
10- // This test verifies that when passing arguments to functions, the actual CALL instruction
11- // does not have the compiler_move debug scope, even though the argument itself might be
12- // annotated with compiler_move in MIR.
13- //
14- // Note: On most ABIs, large structs are passed by pointer even when written as "by value",
15- // so there may not be an actual memcpy operation to attach compiler_move to. This test
16- // mainly verifies that IF debug info is emitted, the call itself uses the source location.
15+ #[ derive( Clone , Copy ) ]
16+ pub struct MediumStruct {
17+ pub data : [ u64 ; 5 ] , // 40 bytes
18+ }
19+
20+ pub struct SmallStruct {
21+ pub x : u32 , // 4 bytes
22+ }
23+
24+ // ============================================================================
25+ // Test 1: Single argument call
26+ // ============================================================================
27+
28+ // CHECK-LABEL: call_arg_scope::test_call_with_single_arg
29+ pub fn test_call_with_single_arg ( s : LargeStruct ) {
30+ // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL1_ARG_LOC:]]
31+ // CHECK: call {{.*}}@{{.*}}helper_single{{.*}}({{.*}}), !dbg ![[#CALL1_LOC:]]
32+ helper_single ( s) ;
33+ }
34+
35+ #[ inline( never) ]
36+ fn helper_single ( _s : LargeStruct ) { }
37+
38+ // ============================================================================
39+ // Test 2: Multiple arguments of different types
40+ // ============================================================================
41+
42+ // CHECK-LABEL: call_arg_scope::test_call_with_multiple_args
43+ pub fn test_call_with_multiple_args ( large : LargeStruct , medium : MediumStruct , small : SmallStruct ) {
44+ // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG1_LOC:]]
45+ // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG2_LOC:]]
46+ // CHECK: call {{.*}}@{{.*}}helper_multiple{{.*}}({{.*}}), !dbg ![[#CALL2_LOC:]]
47+ helper_multiple ( large, medium, small) ;
48+ }
49+
50+ #[ inline( never) ]
51+ fn helper_multiple ( _l : LargeStruct , _m : MediumStruct , _s : SmallStruct ) { }
52+
53+ // ============================================================================
54+ // Test 3: Return value
55+ // ============================================================================
1756
18- // CHECK-LABEL: call_arg_scope::test_call_with_move
19- pub fn test_call_with_move ( s : LargeStruct ) {
20- // The key test: the call instruction should reference the source line (line 22),
21- // NOT a compiler_move scope.
22- helper ( s ) ;
57+ // CHECK-LABEL: call_arg_scope::test_return_large_value
58+ pub fn test_return_large_value ( ) -> LargeStruct {
59+ let s = LargeStruct { data : [ 42 ; 20 ] } ;
60+ // CHECK: ret {{.*}}, !dbg ![[#RET1_LOC:]]
61+ s
2362}
2463
25- // Find the call instruction and verify its debug location
26- // CHECK: call {{.*}}@{{.*}}helper{{.*}}({{.*}}), !dbg ![[CALL_LOC:[0-9]+]]
64+ // ============================================================================
65+ // Test 4: Calling a function that returns a large value
66+ // ============================================================================
2767
28- // Verify that the call's debug location points to line 22 (the actual source line)
29- // and NOT to a scope with inlinedAt referencing compiler_move
30- // CHECK: ![[CALL_LOC]] = !DILocation(line: 22,
68+ // CHECK-LABEL: call_arg_scope::test_call_returning_large
69+ pub fn test_call_returning_large ( ) {
70+ // CHECK: call {{.*}}@{{.*}}make_large_struct{{.*}}({{.*}}), !dbg ![[#CALL3_LOC:]]
71+ let _result = make_large_struct ( ) ;
72+ }
3173
3274#[ inline( never) ]
33- fn helper ( _s : LargeStruct ) { }
75+ fn make_large_struct ( ) -> LargeStruct {
76+ LargeStruct { data : [ 1 ; 20 ] }
77+ }
78+
79+ // ============================================================================
80+ // Test 5: Mixed scenario - passing and returning large values
81+ // ============================================================================
82+
83+ // CHECK-LABEL: call_arg_scope::test_mixed_call
84+ pub fn test_mixed_call ( input : LargeStruct ) -> LargeStruct {
85+ // CHECK: call {{.*}}@{{.*}}transform_large{{.*}}({{.*}}), !dbg ![[#CALL4_LOC:]]
86+ transform_large ( input)
87+ }
88+
89+ #[ inline( never) ]
90+ fn transform_large ( mut s : LargeStruct ) -> LargeStruct {
91+ s. data [ 0 ] += 1 ;
92+ s
93+ }
94+
95+ // CHECK-DAG: ![[#CALL1_ARG_LOC]] = !DILocation({{.*}}scope: ![[#CALL1_ARG_SCOPE:]]
96+ // CHECK-DAG: ![[#CALL1_ARG_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<call_arg_scope::LargeStruct, 160>"
97+ // CHECK-DAG: ![[#CALL1_LOC]] = !DILocation({{.*}}scope: ![[#CALL1_SCOPE:]]
98+ // CHECK-DAG: ![[#CALL1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_with_single_arg"
99+
100+ // CHECK-DAG: ![[#CALL2_ARG1_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_ARG1_SCOPE:]]
101+ // CHECK-DAG: ![[#CALL2_ARG1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<call_arg_scope::LargeStruct, 160>"
102+ // CHECK-DAG: ![[#CALL2_ARG2_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_ARG2_SCOPE:]]
103+ // CHECK-DAG: ![[#CALL2_ARG2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<call_arg_scope::MediumStruct, 40>"
104+ // CHECK-DAG: ![[#CALL2_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_SCOPE:]]
105+ // CHECK-DAG: ![[#CALL2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_with_multiple_args"
106+
107+ // CHECK-DAG: ![[#CALL3_LOC]] = !DILocation({{.*}}scope: ![[#CALL3_SCOPE:]]
108+ // CHECK-DAG: ![[#CALL3_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_returning_large"
109+
110+ // CHECK-DAG: ![[#CALL4_LOC]] = !DILocation({{.*}}scope: ![[#CALL4_SCOPE:]]
111+ // CHECK-DAG: ![[#CALL4_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_mixed_call"
112+
113+ // CHECK-DAG: ![[#RET1_LOC]] = !DILocation({{.*}}scope: ![[#RET1_SCOPE:]]
114+ // CHECK-DAG: ![[#RET1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_return_large_value"
0 commit comments