Refactoring K2 code generation logic #80
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces significant changes to the code generation logic under K2.
Caution
The refactoring in this PR involves significant modifications to the code generation logic under K2, and its full reliability and compatibility cannot be guaranteed at this time.
If you encounter any issues, please actively report them.
Before the Changes
Previously, the code generation flow in K2 was structured as follows:
Take the following code as an example:
The plugin would first resolve
meow
during the FIR phase, then generate two synthetic functions (meowBlocking
andmeowAsync
) without bodies, which would later proceed to the IR phase.At this stage, the plugin also needed to preserve and pass the mappings between
meow -> meowBlocking
andmeow -> meowAsync
, as the IR phase required generatingbody
for synthetic functions (which involve invoking the original function).However, since most FIR and IR types are incompatible, this approach caused complications and led to issues like #72 and #67.
How did we preserve these mappings before? Simply by converting function names and parameter types (as strings) into neutral types stored in
PluginKey
. However, this method proved unreliable in cases involvingtypealias
and was inefficient due to redundant function traversals during the IR phase.Intermediate Phase
To address issues with
typealias
, generics, and other challenges, #73 introduced a new marker annotation@TargetMarker
. The idea (detailed in #73 and #75) was to establish a correspondence between synthetic and original functions using a unique ID in the annotation.While #73 resolved #72, some unreproducible edge cases remained. As a workaround, #76 reverted to the original logic when the new approach failed.
After the Changes
While reviewing code (unsure of the source), I discovered that FIR could also generate
body
, which inspired #75. The initial refactor involved generating internal bridge functions during the FIR phase:By combining
TargetMarker
with a unique ID, the IR phase could directly generate bodies for these bridge functions, eliminating unreliable mappings and redundant traversals. Later I realized FIR could generate more complex bodies (e.g., referencing external functions/types), allowing full synthetic function generation without bridge functions.This PR now directly generates complete synthetic functions (
meowBlocking
andmeowAsync
) during FIR, removing the need for IR-phase adjustments.Testing
Given the extensive code changes, full reliability and compatibility cannot yet be guaranteed.
In the test files, both FIR and IR outputs show significant differences, but the final ASM files remain unchanged. This suggests binary compatibility with previous outputs.
A downstream project using this plugin also shows no compatibility issues (verified via binary-compatibility-validator).
Local testing for the JS platform revealed no issues so far.
Conclusion
Theoretically, these changes should improve efficiency and reduce instability caused by unreliable type mapping mechanisms.
close #75