[Research] Discover how pointer constness affects pointer parameter codegen

In most cases, this discovery will mean that we have to bite the bullet
and remove `const` from pointer parameters if the generated ASM
wouldn't match otherwise. That by itself doesn't really simplify the
code, but at least we get to remove a single bloated `reinterpret_cast`
from one function call already.

Part of P0278, funded by Yanga.
This commit is contained in:
nmlgc 2024-04-04 18:47:58 +02:00
parent 5359bff77b
commit c96952f47b
4 changed files with 17 additions and 9 deletions

View File

@ -362,8 +362,14 @@ certain local variables as `word`s when they aren't.
### Pushing pointers
When passing a `near` pointer to a function that takes a `far` one, the
segment argument is sometimes `PUSH`ed immediately, before evaluating the
Passing `far` pointers to subscripted array elements requires code to calculate
the offset. Turbo C++ emits this calculation (and not the `PUSH` itself) either
before or after the segment is `PUSH`ed. If either
1. the pointer is `near`, or
2. the parameter is a near or far `const *`,
the segment argument is always pushed immediately, before evaluating the
offset:
```c++
@ -375,11 +381,14 @@ struct s100 {
extern s100 structs[5];
void __cdecl process(s100 *element);
void __cdecl process_mut(s100 *element);
void __cdecl process_const(const s100 *element);
void foo(int i) {
process((s100 near *)(&structs[i])); // PUSH DS; (AX = offset); PUSH AX;
process((s100 far *)(&structs[i])); // (AX = offset); PUSH DS; PUSH AX;
process_mut((s100 near *)(&structs[i])); // PUSH DS; (AX = offset); PUSH AX;
process_mut((s100 far *)(&structs[i])); // (AX = offset); PUSH DS; PUSH AX;
process_const((s100 near *)(&structs[i])); // PUSH DS; (AX = offset); PUSH AX;
process_const((s100 far *)(&structs[i])); // PUSH DS; (AX = offset); PUSH AX;
}
```

View File

@ -603,7 +603,7 @@ static const int SCOREDAT_NOT_CLEARED = (SCOREDAT_CLEARED - 10);
void regist_menu(
score_t score,
int16_t stage_num_or_scoredat_constant,
const sshiftjis_t route[SCOREDAT_ROUTE_LEN + 1]
sshiftjis_t route[SCOREDAT_ROUTE_LEN + 1]
)
{
scoredat_name_z_t names[SCOREDAT_PLACES];

View File

@ -18,5 +18,5 @@
void regist_menu(
score_t score,
int16_t stage_num_or_scoredat_constant,
const sshiftjis_t route[SCOREDAT_ROUTE_LEN + 1]
sshiftjis_t route[SCOREDAT_ROUTE_LEN + 1]
);

View File

@ -1006,8 +1006,7 @@ int main(void)
}
resident->score = score;
// ZUN bloat: Unnecessary cast.
regist_menu(score, (stage_id + 1), reinterpret_cast<const sshiftjis_t *>(
regist_menu(score, (stage_id + 1), (
!stage_on_route(stage_id) ? SCOREDAT_ROUTE_SHRINE :
(route == ROUTE_MAKAI) ? SCOREDAT_ROUTE_MAKAI : SCOREDAT_ROUTE_JIGOKU
));