/*
 * Copyright 2017 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.
 */

//
// Instruments the build with code to intercept all local reads and writes.
//
// gets:
//
//  Before:
//   (local.get $x)
//
//  After:
//    (call $get_TYPE
//     (i32.const n) // call id
//     (i32.const n) // local id
//     (local.get $x)
//    )
//
// sets:
//
//  Before:
//   (local.set $x (i32.const 1))
//
//  After:
//   (local.set $x
//    (call $set_TYPE
//     (i32.const n) // call id
//     (i32.const n) // local id
//     (i32.const 1) // value
//    )
//   )

#include "asmjs/shared-constants.h"
#include "shared-constants.h"
#include <pass.h>
#include <wasm-builder.h>
#include <wasm.h>

namespace wasm {

static const Name get_i32("get_i32");
static const Name get_i64("get_i64");
static const Name get_f32("get_f32");
static const Name get_f64("get_f64");
static const Name get_v128("get_v128");
static const Name get_funcref("get_funcref");
static const Name get_externref("get_externref");

static const Name set_i32("set_i32");
static const Name set_i64("set_i64");
static const Name set_f32("set_f32");
static const Name set_f64("set_f64");
static const Name set_v128("set_v128");
static const Name set_funcref("set_funcref");
static const Name set_externref("set_externref");

struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
  // Adds calls to new imports.
  bool addsEffects() override { return true; }

  void visitLocalGet(LocalGet* curr) {
    Builder builder(*getModule());
    Name import;
    if (curr->type.isRef()) {
      auto heapType = curr->type.getHeapType();
      if (heapType == HeapType::func && curr->type.isNullable()) {
        import = get_funcref;
      } else if (heapType == HeapType::ext && curr->type.isNullable()) {
        import = get_externref;
      } else {
        WASM_UNREACHABLE("TODO: general reference types");
      }
    } else {
      TODO_SINGLE_COMPOUND(curr->type);
      switch (curr->type.getBasic()) {
        case Type::i32:
          import = get_i32;
          break;
        case Type::i64:
          return; // TODO
        case Type::f32:
          import = get_f32;
          break;
        case Type::f64:
          import = get_f64;
          break;
        case Type::v128:
          import = get_v128;
          break;
        case Type::none:
        case Type::unreachable:
          WASM_UNREACHABLE("unexpected type");
      }
    }
    replaceCurrent(builder.makeCall(import,
                                    {builder.makeConst(int32_t(id++)),
                                     builder.makeConst(int32_t(curr->index)),
                                     curr},
                                    curr->type));
  }

  void visitLocalSet(LocalSet* curr) {
    // We don't instrument pop instructions. They are automatically deleted when
    // writing binary and generated when reading binary, so they don't work with
    // local set/get instrumentation.
    if (curr->value->is<Pop>()) {
      return;
    }

    Builder builder(*getModule());
    Name import;
    auto type = curr->value->type;
    if (type.isFunction() && type.getHeapType() != HeapType::func) {
      // FIXME: support typed function references
      return;
    }
    if (type.isRef()) {
      auto heapType = type.getHeapType();
      if (heapType == HeapType::func && type.isNullable()) {
        import = set_funcref;
      } else if (heapType == HeapType::ext && type.isNullable()) {
        import = set_externref;
      } else {
        WASM_UNREACHABLE("TODO: general reference types");
      }
    } else {
      TODO_SINGLE_COMPOUND(curr->value->type);
      switch (type.getBasic()) {
        case Type::i32:
          import = set_i32;
          break;
        case Type::i64:
          return; // TODO
        case Type::f32:
          import = set_f32;
          break;
        case Type::f64:
          import = set_f64;
          break;
        case Type::v128:
          import = set_v128;
          break;
        case Type::unreachable:
          return; // nothing to do here
        case Type::none:
          WASM_UNREACHABLE("unexpected type");
      }
    }
    curr->value = builder.makeCall(import,
                                   {builder.makeConst(int32_t(id++)),
                                    builder.makeConst(int32_t(curr->index)),
                                    curr->value},
                                   curr->value->type);
  }

  void visitModule(Module* curr) {
    addImport(curr, get_i32, {Type::i32, Type::i32, Type::i32}, Type::i32);
    addImport(curr, get_i64, {Type::i32, Type::i32, Type::i64}, Type::i64);
    addImport(curr, get_f32, {Type::i32, Type::i32, Type::f32}, Type::f32);
    addImport(curr, get_f64, {Type::i32, Type::i32, Type::f64}, Type::f64);
    addImport(curr, set_i32, {Type::i32, Type::i32, Type::i32}, Type::i32);
    addImport(curr, set_i64, {Type::i32, Type::i32, Type::i64}, Type::i64);
    addImport(curr, set_f32, {Type::i32, Type::i32, Type::f32}, Type::f32);
    addImport(curr, set_f64, {Type::i32, Type::i32, Type::f64}, Type::f64);

    if (curr->features.hasReferenceTypes()) {
      Type func = Type(HeapType::func, Nullable);
      Type ext = Type(HeapType::ext, Nullable);

      addImport(curr, get_funcref, {Type::i32, Type::i32, func}, func);
      addImport(curr, set_funcref, {Type::i32, Type::i32, func}, func);
      addImport(curr, get_externref, {Type::i32, Type::i32, ext}, ext);
      addImport(curr, set_externref, {Type::i32, Type::i32, ext}, ext);
    }
    if (curr->features.hasSIMD()) {
      addImport(curr, get_v128, {Type::i32, Type::i32, Type::v128}, Type::v128);
      addImport(curr, set_v128, {Type::i32, Type::i32, Type::v128}, Type::v128);
    }
  }

private:
  Index id = 0;

  void addImport(Module* wasm, Name name, Type params, Type results) {
    auto import = Builder::makeFunction(
      name, Type(Signature(params, results), NonNullable, Inexact), {});
    import->module = ENV;
    import->base = name;
    wasm->addFunction(std::move(import));
  }
};

Pass* createInstrumentLocalsPass() { return new InstrumentLocals(); }

} // namespace wasm
