Related to #1272.
After the fix in #1272, async subtasks now transition correctly. However, this exposes another issue in _lowerImport, where the return address is not handled correctly.
This is the generated code:
function _lowerImport(args, exportFn) {
const params = [...arguments].slice(2);
_debugLog("[_lowerImport()] args", {
args,
params,
exportFn
});
const { functionIdx, componentIdx, isAsync, paramLiftFns, resultLowerFns, metadata, memoryIdx, getMemoryFn, getReallocFn } = args;
const parentTask = getCurrentTask(componentIdx)?.task;
if (!parentTask) throw new Error("missing parent task during lower of import");
const cstate = getOrCreateAsyncState(componentIdx);
const subtask = parentTask.createSubtask({
componentIdx,
parentTask,
callMetadata: {
memoryIdx,
memory: getMemoryFn(),
realloc: getReallocFn(),
resultPtr: params[0]
}
});
// cont.
Actual behavior
resultPtr is always set to params[0]
In cases where the function has both parameters and a return value:
params[0] corresponds to the first argument
- the return address is passed as a later parameter (e.g.
params[1])
As a result, the argument value is incorrectly used as a memory address, leading to an incorrect return value.
Example
async function bar(v) { return v + 32; }
In this case:
params[0]: argument (v)
params[1]: return address
Expected behavior
- resultPtr should point to the return address (e.g. params[1] in this case)
Suggestion
The return pointer should be taken from the last parameter, for example:
Using params.at(-1) for resultPtr seems to align with the canonical ABI, where the return pointer is typically passed as the last parameter.
This works correctly in the tested cases, although the exact conditions under which a return pointer is present may need to be handled explicitly.
Related to #1272.
After the fix in #1272, async subtasks now transition correctly. However, this exposes another issue in
_lowerImport, where the return address is not handled correctly.This is the generated code:
Actual behavior
resultPtris always set toparams[0]In cases where the function has both parameters and a return value:
params[0]corresponds to the first argumentparams[1])As a result, the argument value is incorrectly used as a memory address, leading to an incorrect return value.
Example
In this case:
params[0]: argument (v)params[1]: return addressExpected behavior
Suggestion
The return pointer should be taken from the last parameter, for example:
Using
params.at(-1)forresultPtrseems to align with the canonical ABI, where the return pointer is typically passed as the last parameter.This works correctly in the tested cases, although the exact conditions under which a return pointer is present may need to be handled explicitly.