Skip to content

Ranged callee emits type-mismatched alias select, producing a silently wrong result #66

Description

@thiremani

Status: fixed in 61693ce on PR #65. This body was corrected after review;
see the comment below for the implemented fix, which differs from the approach
originally suggested here.

Summary

directParamValue builds the hidden alias select chain over every output of a
function. When a range-bearing callee has a direct scalar parameter and a sibling
output that lowers to a different LLVM type, the chain emits a select between
mismatched types and then an arithmetic op on the wrong type.

The program compiles and returns a wrong answer. LLVM's in-memory verifier does
reject the function (Function is broken), but the compiler does not run
verification, so nothing surfaces it — see #68 for why verification is currently
unavailable. Depending on the shape it can also abort object emission rather than
merely return a wrong value.

Reproduce

lib.pt

sum, half = M2(a, x)
    sum = a + x
    half = x * 0.5

t.spt

s = 1
h = 0.0
s, h = M2(s, 0:4)
"S: -s H: -h"

Expected S: 7 H: 1.5 (s accumulates 1→1→2→4→7). Actual:

S: 0 H: 1.5

Emitted IR

From pluto -emit-ir, inside @Pt_3isa_p_2M2_f2_I64_Range_t1_I64:

%a_alias_value_0 = select i1 %a_alias_match_0, i64 %sum_alias_load_0, i64 %1
%a_alias_value_1 = select i1 %a_alias_match_1, double %half_alias_load_1, i64 %a_alias_value_0
%add_tmp = add double %a_alias_value_1, i64 %iter

The second select mixes double and i64, and the following add inherits it.

Cause

processParams passes the function's complete output-name list to
bindParamAlias, and directParamValue folds each of those outputs into a select
against the scalar parameter value. coerceSymbolForType only bridges Str/Array/Table
flavors; with an Int/Float target it returns the output's own type unchanged, so
the operand types diverge.

Trigger conditions

  • the variant has at least one Range/ArrayRange parameter, so direct scalars get alias slots
  • at least one direct I64/F64 parameter is actually read in the callee body
  • at least one output lowers to a different LLVM type than that parameter

A single mismatched output is enough, and actual caller aliasing is not required:
selector zero still emits the invalid select. A Str or Array sibling output
reproduces it too.

Scope

Pre-existing. Reproduces identically on 9fca83a and on the branch tip before the
fix, so it is not a regression from any recent PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions