hamzaremmal/amy

View on GitHub
compiler/src/main/scala/amyc/backend/wasm/utils/Utils.scala

Summary

Maintainability
A
0 mins
Test Coverage
B
85%
package amyc.backend.wasm.utils

import amyc.reporter
import amyc.core.{Context, Identifier}
import amyc.core.Symbols.*
import amyc.backend.wasm.Instructions.*
import amyc.backend.wasm.builtin.amy.Boolean.mkBoolean
import amyc.backend.wasm.Indices.{globalidx, localidx}
import amyc.backend.wasm.Types.{local as l, *}
import amyc.backend.wasm.handlers.{LocalsHandler, ModuleHandler}

  @deprecated
  val maxParamsInFun = 5

  // ==============================================================================================
  // ================================== WASM FUNCTION TYPES =======================================
  // ==============================================================================================

  @deprecated
  lazy val defaultFunTypes : Context ?=> List[String] =
    s"(type $$${mkFunTypeName(0)} (func (result i32)))"::
    s"(type $$${mkFunTypeName(1)} (func (param i32) (result i32)))" ::
    s"(type $$${mkFunTypeName(2)} (func (param i32 i32) (result i32)))" ::
    s"(type $$${mkFunTypeName(3)} (func (param i32 i32 i32) (result i32)))" ::
    s"(type $$${mkFunTypeName(4)} (func (param i32 i32 i32 i32) (result i32)))" ::
    s"(type $$${mkFunTypeName(5)} (func (param i32 i32 i32 i32 i32) (result i32)))" ::
    Nil

  @deprecated
  def mkFunTypeName(params: Int)(using Context) : String =
    if(params <= maxParamsInFun)
      s"fun_$params"
    else
      reporter.fatal(s"WASM don't define function types for $params parameters")

  // ==============================================================================================
  // =============================== CODE GENERATOR FUNCTIONS =====================================
  // ==============================================================================================

  // Given a pointer to an ADT on the top of the stack,
  // will point at its field in index (and consume the ADT).
  // 'index' MUST be 0-based.
  inline def adtField(inline base: Code, inline index: Int): Code =
    base <:>
    i32.const(4* (index + 1)) <:>
    i32.add

  // Increment a local variable
  inline def incr(inline l: localidx) =
    local.get(l) <:> i32.const(1) <:> i32.add <:> local.set(l)

  inline def withComment(inline comment : String)(inline code: Code) : Code =
    Comment(comment) <:> code

  inline def and(inline lhs: Code, inline rhs: Code) : Code =
    ift(lhs, rhs, mkBoolean(false))

  inline def or(lhs: Code, rhs: Code) : Code =
    ift(lhs, mkBoolean(true), rhs)

  inline def error(inline msg: Code) : Code =
    msg <:> call("Std_printString") <:> unreachable

  inline def ift(inline cond: Code, inline thenn: Code, inline elze: Code): Code  =
    cond <:>
    `if`(None, Some(result(i32))) <:>
    thenn <:>
    `else`() <:>
    elze <:> end