Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/fpy/codegen_fpybc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,13 +1215,14 @@ def emit_AstAssign(self, node: AstAssign, state: CompileState):
dirs.append(IntAddDirective())

# Add the constant part: base variable's frame offset +
# accumulated constant field offsets.
# accumulated constant field offsets. Signed, because a parameter
# sits below the frame start at a negative offset.
const_part = base_frame_offset + field_const_offset
dirs.append(PushValDirective(FpyValue(U64, const_part).serialize()))
dirs.append(PushValDirective(FpyValue(I64, const_part).serialize()))
dirs.append(IntAddDirective())

# and now convert the u64 back into the SignedStackSizeType that store expects
dirs.extend(self.convert_numeric_type(U64, SignedStackSizeType))
# and now convert the i64 back into the SignedStackSizeType that store expects
dirs.extend(self.convert_numeric_type(I64, SignedStackSizeType))

# now that the frame offset is pushed, use it to store into the frame
if use_abs:
Expand Down
37 changes: 37 additions & 0 deletions test/fpy/test_types_and_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,43 @@ def pick(idx: I8) -> U32:
"""
assert_run_success(fprime_test_api, seq)

def test_assign_param_array_element_runtime_index(self, fprime_test_api):
"""A store through a runtime index into an array parameter. Parameters
live at negative frame offsets, and the store must land on the right
element without touching its neighbors."""
seq = """
def f(a: Ref.FpyExampleArray, i: I64) -> U32:
a[i] = 7
assert a[0] == 1
assert a[2] == 3
return a[i]

arr: Ref.FpyExampleArray = Ref.FpyExampleArray(1, 2, 3)
k: I64 = 1
assert f(arr, k) == 7
"""
assert_run_success(fprime_test_api, seq)

def test_assign_param_array_element_member_runtime_index(self, fprime_test_api):
"""A store into a struct member of a runtime-indexed element of an
array-of-struct parameter."""
seq = """
def set_value(pairs: Ref.SignalPairSet, i: I64, v: F32) -> F32:
pairs[i].value = v
assert pairs[i].time == 5.0
assert pairs[1].value == 4.0
return pairs[i].value

p: Ref.SignalPairSet = Ref.SignalPairSet( \\
Ref.SignalPair(1.0, 2.0), \\
Ref.SignalPair(3.0, 4.0), \\
Ref.SignalPair(5.0, 6.0), \\
Ref.SignalPair(7.0, 8.0))
idx: I64 = 2
assert set_value(p, idx, 99.0) == 99.0
"""
assert_run_success(fprime_test_api, seq)

def test_assign_array_element_two_runtime_indices(self, fprime_test_api):
"""A store whose access chain has two runtime indices: each index
needs its own bounds check."""
Expand Down
Loading