Skip to content

fix!(codegen): reset function outputs and default omitted arguments - #1958

Open
Angus-Bethke-Bachmann wants to merge 5 commits into
masterfrom
anbt/PRG-4940
Open

Angus-Bethke-Bachmann wants to merge 5 commits into
masterfrom
anbt/PRG-4940

Conversation

@Angus-Bethke-Bachmann

Copy link
Copy Markdown
Contributor

@ghaith or @volsa this one needs a careful review, it made some assumptions in codegen that seem right... but a few of the polymorphism tests have been changed. So a double check of this is probably necessary.

Problem: When a call left out an argument, the compiler passed the contents of a stack slot that nothing had written. The callee then saw whatever the previous call had left there. A VAR_OUTPUT of a function or method also started every call with the caller's current value, so a path that did not assign the output leaked that value back to the caller.

Solution: An argument that is left out, or written empty, now carries the declared default or zero. Every VAR_OUTPUT of a function or method is initialized like a local variable at the start of the call: codegen zero-fills it through the caller's address, and the init lowering adds the constructor call and the initializer assignment. Variable length array outputs keep the caller's bounds and are not reset. Reading an output before assigning it now gives its default, so callers no longer observe stale values. One known effect is that passing the same variable as an output and as an in-out of one call makes the body read zero; the book documents this.

Refs: PRG-4940

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

3 findings in 4m 31s for $0.73 between f7d42e8 (master) and faf4f52 (anbt/PRG-4940):

  • P2 book/user/language/functions.md:68: The claim that every output starts at its initial value or zero is too broad: codegen deliberately does not reset variable-length-array, REFERENCE TO, or alias outputs. Qualify the guarantee with these exceptions so readers are not led to expect their caller-owned storage to be cleared.
  • P2 book/user/language/methods-and-properties.md:38: This still tells readers they must supply every method parameter and says an omitted parameter without a default has no defined value. Method calls now allow any parameter to be omitted and codegen supplies its default or zero, so update this paragraph to describe that behavior.
  • P2 src/codegen/generators/pou_generator.rs:982: Runtime output defaults are evaluated without a function context: a method declaring VAR_OUTPUT p : POINTER TO Fb := ADR(THIS^); END_VAR now fails code generation. Static trace (not executed): maybe_get_constant_statement returns this address-unresolvable initializer, and generate_variable_initializer evaluates it with new_context_free, causing the THIS branch to return Cannot use 'this' without context. The lowered stack initializer can handle this expression, but the new prologue rejects it before that initializer runs.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Build Artifacts

🐧 Linux

Artifact Link Size
schema Download 0.0 MB
deb-x86_64 Download 38.5 MB
stdlib Download 32.4 MB
plc-x86_64 Download 43.6 MB
deb-aarch64 Download 30.9 MB
plc-aarch64 Download 43.4 MB

From workflow run

🪟 Windows

Artifact Link Size
plc.exe Download 38.4 MB
stdlib.dll Download 0.1 MB
stdlib.lib Download 4.0 MB

From workflow run

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

2 findings in 5m 10s for $0.72 between 5adf03e (master) and 75d231e (anbt/PRG-4940):

  • P2 book/user/language/functions.md:68: The aliasing warning says the shared input/in-out will read as zero, but an output with a nonzero initializer is reset to that initializer before the body runs. Describe the value as the output's initialized value (or zero when it has none), otherwise this example of the new behavior is inaccurate.
  • P2 book/user/language/methods-and-properties.md:38: The new claim that a method call may omit any parameter contradicts validation: src/validation/statement.rs:2484-2507 still requires every VAR_IN_OUT parameter and REFERENCE TO input, reporting E030 when one is omitted. For example, fb.m() with m declaring VAR_IN_OUT x : DINT fails compilation instead of receiving the documented initialized temporary; the same incorrect rule also appears in the updated technical codegen page (static trace, untested).

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant