Skip to content

[WebAssembly] Loop that shouldn't be given a return type #138394

Closed
@Photosounder

Description

@Photosounder

I could be wrong about this one because Wasm control flow is confusing, but I'm 85% sure this C function compiles to something it shouldn't:

intmax_t make_power_of_10_int(int p)
{
	intmax_t v = 1;

	while (p >= 5) { v *= 100000; p -= 5; }
	while (p >= 1) { v *= 10;     p -= 1; }

	return v;
}

Using -Oz this compiles to:

make_power_of_10_int:
    i64.const         1
    local.set         1

        loop              i64
            block

            local.get       0
            i32.const       4
            i32.gt_s
            br_if           0

                block
                    loop

                    local.get       0
                    i32.const       1
                    i32.lt_s
                    br_if           1

                    local.get       0
                    i32.const       -1
                    i32.add
                    local.set       0

                    local.get       1
                    i64.const       10
                    i64.mul
                    local.set       1

                    br              0
                    end_loop
                end_block

            local.get       1
            return

            end_block

        local.get         0
        i32.const         -5
        i32.add
        local.set         0

        local.get         1
        i64.const         100000
        i64.mul
        local.set         1

        br                0
        end_loop

    end_function

The problem is that:

  • The first (outermost) loop has a i64 return type, but at the 4th line from the bottom local.set 1 empties the stack.
  • This loop branches unconditionally with br 0, so even if there was something in the stack it could never be used.
  • This loop and the whole function can only end through return.
  • The result is stored in local1 anyway, I can't see why the loop would need a return type.

Therefore the most immediately obvious conclusion is that giving that loop a return type is a mistake because it doesn't actually return anything (due to empty stack) and it can never exit normally anyway. I guess it would make sense if at the end of the loop the last local.set was treated as a local.tee, but I see no reason to believe things are supposed to work like this.

This problem seems specific to -Oz as the other optimisation settings produce totally different Wasm.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend:WebAssemblyquestionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions