/*
 * Copyright 2021 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef wasm_ir_intrinsics_h
#define wasm_ir_intrinsics_h

#include "pass.h"
#include "wasm-traversal.h"

//
// Intrinsics include Binaryen intrinsics, and Wasm spec builtins. See the
// README.md for more.
//
// Intrinsics can be recognized by Intrinsics::isFoo() methods, that check if a
// function is a particular intrinsic, or if a call to a function is so. The
// latter returns nullptr if the input is not that intrinsic, and otherwise the
// intrinsic itself cast to a Call*.
//

namespace wasm {

class Intrinsics {
  const Module& module;

public:
  Intrinsics(const Module& module) : module(module) {}

  // Check if an instruction is the Binaryen call.without.effects intrinsic.
  //
  //   (import "binaryen-intrinsics" "call.without.effects"
  //     (func (..params..) (param $target funcref) (..results..)))
  //
  // call.without.effects can take any parameters, and in addition a funcref,
  // and return any result.
  //
  // Precise semantics:
  //
  //  * The optimizer will assume this instruction has no side effects.
  //  * Final lowering turns a call.without.effects into a call of the given
  //    function with the given parameters. (This will either be a direct call,
  //    or a call_ref; note that either way, the function reference that appears
  //    here must have the proper type - if not, you will get an error.)
  //
  // call.without.effects is useful to be able to get rid of an unused result
  // that has side effects. For example,
  //
  //  (drop (call $get-something))
  //
  // cannot be removed, as a call has side effects. But if a code generator
  // knows that it is fine to not make the call given that the result is
  // dropped (perhaps the side effects are to initialize a global cache, for
  // example) then instead of emitting
  //
  //   (call $get-something)
  //
  // it can emit
  //
  //   (call $call.without.effects (ref.func $get-something))
  //
  // which will have this behavior in the optimizer if it is dropped:
  //
  //  (drop (call $call.without.effects (ref.func $get-something)))
  //     =>
  //  (drop (ref.func $get-something))
  //
  // Later optimizations can remove the dropped ref.func. Or, if the result is
  // actually used,
  //
  //  (local.set $x (call $call.without.effects (ref.func $get-something)))
  //     =>
  //  (local.set $x (call $get-something))
  //
  // Later passes will then turn that into a direct call and further optimize
  // things.
  bool isCallWithoutEffects(Function* func);
  Call* isCallWithoutEffects(Expression* curr);

  // Check if an instruction is the wasm/JS interop configureAll builtin. Such
  // calls have a second parameter which is an array of function references,
  // which must be assumed to be "signature-called": Called from outside the
  // module, using that signature. "Signature-called" is less powerful than the
  // reference to the function generally escaping, as we do not care about the
  // heap type of the function (no call_refs or casts will happen), all we know
  // is that a JS-style call of the methods can occur (and only the signature
  // matters then).
  bool isConfigureAll(Function* func);
  Call* isConfigureAll(Expression* curr);
  // Given a configureAll, return all the functions it refers to. We error if it
  // is not in the canonical form
  //
  //  (call $configureAll
  //    ..arg0..
  //    (array.new_elem $seg (0) (N)
  //    ..
  //  )
  //
  // where the segment $seg is of size N.
  std::vector<Name> getConfigureAllFunctions(Call* call);

  // Returns the names of all functions that are JS-called. That includes ones
  // in configureAll (which we look through the module for), and also those
  // annotated with @binaryen.js.called.
  std::vector<Name> getJSCalledFunctions();

  // Get the code annotations for an expression in a function.
  static CodeAnnotation getAnnotations(Expression* curr, Function* func) {
    auto& annotations = func->codeAnnotations;
    auto iter = annotations.find(curr);
    if (iter != annotations.end()) {
      return iter->second;
    }
    return {};
  }

  // Get the code annotations for a function itself.
  static CodeAnnotation getAnnotations(Function* func) {
    return func->funcAnnotations;
  }

  void setAnnotations(Function* func,
                      Expression* curr,
                      const CodeAnnotation& value) {
    func->codeAnnotations[curr] = value;
  }

  void setAnnotations(Function* func, const CodeAnnotation& value) {
    func->funcAnnotations = value;
  }

  // Given a call in a function, return all the annotations for it. The call may
  // be annotated itself (which takes precedence), or the function it calls may
  // be annotated.
  CodeAnnotation getCallAnnotations(Call* call, Function* func) {
    // Combine annotations from the call itself and from the called function.
    auto ret = getAnnotations(call, func);

    // Check on the called function, if it exists (it may not if the IR is still
    // being built up).
    if (auto* target = module.getFunctionOrNull(call->target)) {
      auto funcAnnotations = getAnnotations(target);

      // Merge them, giving precedence for the call annotation.
      if (!ret.branchLikely) {
        ret.branchLikely = funcAnnotations.branchLikely;
      }
      if (!ret.inline_) {
        ret.inline_ = funcAnnotations.inline_;
      }
      if (!ret.removableIfUnused) {
        ret.removableIfUnused = funcAnnotations.removableIfUnused;
      }
      if (!ret.jsCalled) {
        ret.jsCalled = funcAnnotations.jsCalled;
      }
      if (!ret.idempotent) {
        ret.idempotent = funcAnnotations.idempotent;
      }
      if (!ret.toolchainInline) {
        ret.toolchainInline = funcAnnotations.toolchainInline;
      }
    }

    return ret;
  }
};

} // namespace wasm

#endif // wasm_ir_intrinsics_h
