Skip to content

Commit 826f0aa

Browse files
committed
ctest: Use askama comments rather than source comments.
We don't need the doc comments to be repeated for each invocation, so move them to either once-per-loop comments or to askama comments that get deleted from the template. On one target, this reduced the lines of generated C from 82700 to 62931, and Rust from 255569 to 227735.
1 parent cd1d68b commit 826f0aa

12 files changed

+729
-738
lines changed

ctest/templates/test.c

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,65 +29,78 @@
2929

3030
typedef void (*ctest_void_func)(void);
3131

32+
/* Query a pointer to string constants.
33+
*
34+
* Define a function that returns a pointer to the value of the constant to test.
35+
* This will later be called on the Rust side via FFI.
36+
*/
3237
{%- for const_cstr in ctx.const_cstr_tests +%}
3338

3439
static char *ctest_const_{{ const_cstr.id }}_val_static = {{ const_cstr.c_val }};
3540

36-
// Define a function that returns a pointer to the value of the constant to test.
37-
// This will later be called on the Rust side via FFI.
3841
CTEST_EXTERN char *ctest_const_cstr__{{ const_cstr.id }}(void) {
3942
return ctest_const_{{ const_cstr.id }}_val_static;
4043
}
4144
{%- endfor +%}
4245

46+
47+
/* Query a pointer to non-string constants.
48+
*
49+
* Define a function that returns a pointer to the value of the constant to test.
50+
* This will later be called on the Rust side via FFI.
51+
*/
4352
{%- for constant in ctx.const_tests +%}
4453

4554
static {{ constant.c_ty }} ctest_const_{{ constant.id }}_val_static = {{ constant.c_val }};
4655

47-
// Define a function that returns a pointer to the value of the constant to test.
48-
// This will later be called on the Rust side via FFI.
4956
CTEST_EXTERN {{ constant.c_ty }} *ctest_const__{{ constant.id }}(void) {
5057
return &ctest_const_{{ constant.id }}_val_static;
5158
}
5259
{%- endfor +%}
5360

61+
62+
/* Query the size and alignment of all types */
5463
{%- for item in ctx.size_align_tests +%}
5564

56-
// Return the size of a type.
5765
CTEST_EXTERN uint64_t ctest_size_of__{{ item.id }}(void) { return sizeof({{ item.c_ty }}); }
58-
59-
// Return the alignment of a type.
6066
CTEST_EXTERN uint64_t ctest_align_of__{{ item.id }}(void) { return CTEST_ALIGNOF({{ item.c_ty }}); }
6167
{%- endfor +%}
6268

69+
70+
/* Query the signedness of a type.
71+
*
72+
* Return `1` if the type is signed, otherwise return `0`.
73+
* Casting -1 to the aliased type if signed evaluates to `-1 < 0`, if unsigned to `MAX_VALUE < 0`
74+
*/
6375
{%- for alias in ctx.signededness_tests +%}
6476

65-
// Return `1` if the type is signed, otherwise return `0`.
66-
// Casting -1 to the aliased type if signed evaluates to `-1 < 0`, if unsigned to `MAX_VALUE < 0`
6777
CTEST_EXTERN uint32_t ctest_signededness_of__{{ alias.id }}(void) {
6878
{{ alias.c_ty }} all_ones = ({{ alias.c_ty }}) -1;
6979
return all_ones < 0;
7080
}
7181
{%- endfor +%}
7282

83+
84+
/* Query the offsets of fields and their sizes. */
7385
{%- for item in ctx.field_size_offset_tests +%}
7486

75-
// Return the offset of a struct/union field.
7687
CTEST_EXTERN uint64_t ctest_offset_of__{{ item.id }}__{{ item.field.ident() }}(void) {
7788
return offsetof({{ item.c_ty }}, {{ item.c_field }});
7889
}
7990

80-
// Return the size of a struct/union field.
8191
CTEST_EXTERN uint64_t ctest_size_of__{{ item.id }}__{{ item.field.ident() }}(void) {
8292
return sizeof((({{ item.c_ty }}){}).{{ item.c_field }});
8393
}
8494
{%- endfor +%}
8595

96+
97+
/* Query a pointer to a field given a pointer to its struct */
8698
{%- for item in ctx.field_ptr_tests +%}
8799

88-
// Return a pointer to a struct/union field.
89-
// This field can have a normal data type, or it could be a function pointer or an array, which
90-
// have different syntax. A typedef is used for convenience, but the syntax must be precomputed.
100+
{#
101+
// This field can have a normal data type, or it could be a function pointer or an array, which
102+
// have different syntax. A typedef is used for convenience, but the syntax must be precomputed.
103+
#}
91104
typedef {{ item.volatile_keyword }}{{ item.field_return_type }};
92105
CTEST_EXTERN ctest_field_ty__{{ item.id }}__{{ item.field.ident() }}
93106
ctest_field_ptr__{{ item.id }}__{{ item.field.ident() }}({{ item.c_ty }} *b) {
@@ -107,28 +120,38 @@ ctest_field_ptr__{{ item.id }}__{{ item.field.ident() }}({{ item.c_ty }} *b) {
107120
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
108121
#endif
109122

123+
124+
/* Write a nonrepeating bitpattern to a data type
125+
*
126+
* Tests whether the struct/union/alias `x` when passed by value to C and back to Rust
127+
* remains unchanged.
128+
* It checks if the size is the same as well as if the padding bytes are all in the correct place.
129+
*/
110130
{%- for item in ctx.roundtrip_tests +%}
111131

112-
// Tests whether the struct/union/alias `x` when passed by value to C and back to Rust
113-
// remains unchanged.
114-
// It checks if the size is the same as well as if the padding bytes are all in the correct place.
115132
CTEST_EXTERN {{ item.c_ty }} ctest_roundtrip__{{ item.id }}(
116133
{{ item.c_ty }} value,
117134
const uint8_t is_padding_byte[sizeof({{ item.c_ty }})],
118135
uint8_t value_bytes[sizeof({{ item.c_ty }})]
119136
) {
120137
int size = (int)sizeof({{ item.c_ty }});
121-
// Mark `p` as volatile so that the C compiler does not optimize away the pattern we create.
122-
// Otherwise the Rust side would not be able to see it.
138+
{#
139+
// Mark `p` as volatile so that the C compiler does not optimize away the pattern we create.
140+
// Otherwise the Rust side would not be able to see it.
141+
#}
123142
volatile uint8_t* p = (volatile uint8_t*)&value;
124143
int i = 0;
125144
for (i = 0; i < size; ++i) {
126-
// We skip padding bytes in both Rust and C because writing to it is undefined.
127-
// Instead we just make sure the the placement of the padding bytes remains the same.
145+
{#
146+
// We skip padding bytes in both Rust and C because writing to it is undefined.
147+
// Instead we just make sure the the placement of the padding bytes remains the same.
148+
#}
128149
if (is_padding_byte[i]) { continue; }
129150
value_bytes[i] = p[i];
130-
// After we check that the pattern remained unchanged from Rust to C, we invert the pattern
131-
// and send it back to Rust to make sure that it remains unchanged from C to Rust.
151+
{#
152+
// After we check that the pattern remained unchanged from Rust to C, we invert the pattern
153+
// and send it back to Rust to make sure that it remains unchanged from C to Rust.
154+
#}
132155
uint8_t d = (uint8_t)(255) - (uint8_t)(i % 256);
133156
d = d == 0 ? 42: d;
134157
p[i] = d;
@@ -154,9 +177,9 @@ CTEST_EXTERN {{ item.c_ty }} ctest_roundtrip__{{ item.id }}(
154177
#pragma warning(disable:4191)
155178
#endif
156179

180+
/* Query a function's pointer */
157181
{%- for item in ctx.foreign_fn_tests +%}
158182

159-
// Return a function pointer.
160183
CTEST_EXTERN ctest_void_func ctest_foreign_fn__{{ item.id }}(void) {
161184
return (ctest_void_func){{ item.c_val }};
162185
}
@@ -167,11 +190,14 @@ CTEST_EXTERN ctest_void_func ctest_foreign_fn__{{ item.id }}(void) {
167190
#pragma warning(default:4191)
168191
#endif
169192

193+
194+
/* Query pointers to statics */
170195
{%- for static_ in ctx.foreign_static_tests +%}
171196

172-
// Return a pointer to the static variable content.
173197
CTEST_EXTERN void *ctest_static__{{ static_.id }}(void) {
174-
// FIXME(ctest): Not correct due to casting the function to a data pointer.
198+
{#
199+
// FIXME(ctest): Not correct due to casting the function to a data pointer.
200+
#}
175201
return (void *)&{{ static_.c_val }};
176202
}
177203
{%- endfor +%}

0 commit comments

Comments
 (0)