Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Silently outputting invalid assembly code for a nonsense program #12

Open
FlatAssembler opened this issue Aug 31, 2021 · 0 comments
Open

Comments

@FlatAssembler
Copy link
Owner

For this nonsense AEC code:

Function foo(Integer32 a, Integer32 b) Which Returns Integer32 Does
  Return invertBits(a := b);
EndFunction

The compiler outputs the following assembly code:

;;Generated by AECforWebAssembly ( https://github.com/FlatAssembler/AECforWebAssembly ).
(module 
  (import "JavaScript" "memory" (memory 1)) ;;Assume that, in the JavaScript program linked to this
  ;;AEC program, there is an "extern"-ed bytearray of size 1 page (64KB) called "memory".
  ;;Have a better idea?
  (global $stack_pointer (import "JavaScript" "stack_pointer") (mut i32)) ;;The stack pointer being
  ;;visible from JavaScript will be useful when debugging the compiler. This breaks compatibility with
  ;;WebAssembly environments which do not support "WebAssembly.Global", such as Firefox 52 (the last
  ;;version of Firefox to run on Windows XP, and the first one supporting WebAssembly).
  (func $foo (param i32) (param i32) (result i32) (local $return_value i32)
    (global.set $stack_pointer ;;Allocate the space for the arguments of that function on the system stack.
      (i32.add
        (global.get $stack_pointer)
        (i32.const 8)
      )
    )
    (i32.store 
      (i32.sub
        (global.get $stack_pointer)
        (i32.const 8) ;;a
      )
      (local.get 0)
    )
    (i32.store 
      (i32.sub
        (global.get $stack_pointer)
        (i32.const 4) ;;b
      )
      (local.get 1)
    )
    ;;Setting for returning: (invertBits (:= a b))
    (local.set $return_value
      (i32.xor (i32.const -1)
        ;;Assigning b to a.
        (i32.store
          (i32.sub
            (global.get $stack_pointer)
            (i32.const 8) ;;a
          )
          (i32.load
            (i32.sub
              (global.get $stack_pointer)
              (i32.const 4) ;;b
            )
          )
        )
      )
    )
    (global.set $stack_pointer (i32.sub (global.get $stack_pointer) (i32.const 8))) ;;Cleaning up the system stack before returning.
    (return (local.get $return_value))
    (global.set $stack_pointer (i32.sub (global.get $stack_pointer) (i32.const 8)))
    (i32.const 0)
  )
  (export "foo" (func $foo))
)

That is invalid assembly code, the assembler wat2wasm from WebAssembly Binary Toolkit has this to say about it:

debug.wat:33:8: error: type mismatch in i32.xor, expected [i32, i32] but got [i32]
      (i32.xor (i32.const -1)
       ^^^^^^^

It has to do with the way I implemented named arguments. Namely, when the semantic analyzer sees the := being used inside a built-in (therefore, in its mind, already declared) function, it assumes it is a named argument of that function and passes the nonsensical code to the compiler. Compiler then assumes it is a normal assignment directive (not checking that it is passed as an argument to a built-in function that is invertBits), and outputs invalid assembly code because of that. There does not seem to be a simple solution. We can perhaps modify the semantic analyzer to disallow := being used as an argument to built-in functions, but, then, whenever we add another built-in function, we would need to modify that (or else it will be outdated).

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

No branches or pull requests

1 participant