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