[Chapel Merge] Make the `static typeof` primitive actually static (ensure it has no side effects)

Branch: refs/heads/main
Revision: dc71757ad8040147d67a9391a5dec371e702e95c
Author: DanilaFe
Link: Make the `static typeof` primitive actually static (ensure it has no side effects) by DanilaFe · Pull Request #25621 · chapel-lang/chapel · GitHub
Log Message:
Make the static typeof primitive actually static (ensure it has no side effects) (#25621)

This fixes some niche compilation errors to do with chpl_getStandInRTT
under --baseline (specifically --no-dead-code-elimination).

The Problem

Consider the following comment:

Here, we rely on the fact that static typeof gets only static type
information. That's because instanceObj is null (default-initialized).

The code above is eventually normalized to something like this:

var call_tmp = instanceObj.eltType;
type instanceEltType = __primitive("static typeof", call_tmp);

The normal resolution process replaces the primitive with its result:

var call_tmp = instanceObj.eltType;
type instanceEltType = int; // e.g.

Later, dead code elimination removes the unused call_tmp:

type instanceEltType = int; // e.g.

However, under --baseline, the last step doesn't happen. Which means
that instanceObj.eltType is actually executed. As a result, we end up
with a nil deference error.

Thus, any piece of code that triggers this overload of
chpl_getStandInRTT will crash at runtime.

The Solution

The solution is to avoid normalizing static typeof (and static field type). Instead, at resolution time, these expressions are placed into a
temporary block, resolved there, and the block is then removed. The
result is that no temporaries are left behind, and no side effects occur
even under --baseline.

This implementation piggybacks on PRIM_RESOLVE's, since both of them
avoid normalization through "normal" means.

The alternative solution would have been to manually trace and remove
temporaries as they are created, but that seemed more brittle and
involved.

Reviewed by @benharsh -- thanks!

Testing

  • paratest
  • paratest (baseline)
  • paratest (GASNet)

Compare: Comparing ad1bbdf6a8b32d09186fdb901643d683ca6eccd2...eb84fa57f69a0f23bc9c565bbf3cb2a55741bcf1 · chapel-lang/chapel · GitHub

Diff:
M compiler/passes/normalize.cpp
M compiler/resolution/functionResolution.cpp
M compiler/resolution/preFold.cpp
https://github.com/chapel-lang/chapel/pull/25621.diff