/*
 * Copyright 2024 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 selected function calls.
// This can be e.g. used to trace allocations (malloc, free, calloc, realloc)
// and build tools for memory usage analysis.
// The pass supports SIMD but the multi-value feature is not supported yet.
//
// Instrumenting void free(void*):

// Instrumenting function `void* malloc(int32_t)` with a user-defined
// name of the tracer `trace_alloc` and function `void free(void*)`
// with the default name of the tracer `trace_free` (`trace_` prefix
// is added by default):
// wasm-opt --trace-calls=malloc:trace_alloc,free -o test-opt.wasm test.wasm
//
//  Before:
//   (call $malloc
//     (local.const 32))
//   (call $free (i32.const 64))
//
//  After:
//   (local $0 i32)
//   (local $1 i32)
//   (local $2 i32)
//   (block (result i32)
//     (call $trace_alloc
//       (local.get $0)
//       (local.tee $1
//         (call $malloc
//           (local.tee $0 (i32.const 2))
//         )
//       )
//     )
//   )
//   (block
//     (call $free
//       (local.tee $3
//         (i32.const 64)
//       )
//     )
//     (call $trace_free
//       (local.get $3)
//     )
//   )

#include <map>

#include "asmjs/shared-constants.h"
#include "ir/import-utils.h"
#include "pass.h"
#include "support/string.h"
#include "wasm-builder.h"

namespace wasm {

using TracedFunctions = std::map<Name /* originName */, Name /* tracerName */>;

struct AddTraceWrappers : public WalkerPass<PostWalker<AddTraceWrappers>> {
  AddTraceWrappers(TracedFunctions tracedFunctions)
    : tracedFunctions(std::move(tracedFunctions)) {}
  void visitCall(Call* curr) {
    auto* target = getModule()->getFunction(curr->target);

    auto iter = tracedFunctions.find(target->name);
    if (iter != tracedFunctions.end()) {
      addInstrumentation(curr, target, iter->second);
    }
  }

private:
  void addInstrumentation(Call* curr,
                          const wasm::Function* target,
                          const Name& wrapperName) {
    Builder builder(*getModule());
    std::vector<wasm::Expression*> realCallParams, trackerCallParams;

    for (const auto& op : curr->operands) {
      auto localVar = builder.addVar(getFunction(), op->type);
      realCallParams.push_back(builder.makeLocalTee(localVar, op, op->type));
      trackerCallParams.push_back(builder.makeLocalGet(localVar, op->type));
    }

    auto resultType = target->type.getHeapType().getSignature().results;
    auto realCall = builder.makeCall(target->name, realCallParams, resultType);

    if (resultType.isConcrete()) {
      auto resultLocal = builder.addVar(getFunction(), resultType);
      trackerCallParams.insert(
        trackerCallParams.begin(),
        builder.makeLocalTee(resultLocal, realCall, resultType));

      replaceCurrent(builder.makeBlock(
        {builder.makeCall(
           wrapperName, trackerCallParams, Type::BasicType::none),
         builder.makeLocalGet(resultLocal, resultType)}));
    } else {
      replaceCurrent(builder.makeBlock(
        {realCall,
         builder.makeCall(
           wrapperName, trackerCallParams, Type::BasicType::none)}));
    }
  }

  TracedFunctions tracedFunctions;
};

struct TraceCalls : public Pass {
  // Adds calls to new imports.
  bool addsEffects() override { return true; }

  void run(Module* module) override {
    auto functionsDefinitions =
      getArgument("trace-calls",
                  "TraceCalls usage: wasm-opt "
                  "--trace-calls=FUNCTION_TO_TRACE[:TRACER_NAME][,...]");

    auto tracedFunctions = parseArgument(functionsDefinitions);

    for (const auto& tracedFunction : tracedFunctions) {
      auto func = module->getFunctionOrNull(tracedFunction.first);
      if (!func) {
        std::cerr << "[TraceCalls] Function '" << tracedFunction.first
                  << "' not found" << std::endl;
      } else {
        addImport(module, *func, tracedFunction.second);
      }
    }

    AddTraceWrappers(std::move(tracedFunctions)).run(getPassRunner(), module);
  }

private:
  Type getTracerParamsType(ImportInfo& info, const Function& func) {
    auto resultsType = func.type.getHeapType().getSignature().results;
    if (resultsType.isTuple()) {
      Fatal() << "Failed to instrument function '" << func.name
              << "': Multi-value result type is not supported";
    }

    std::vector<Type> tracerParamTypes;
    if (resultsType.isConcrete()) {
      tracerParamTypes.push_back(resultsType);
    }
    for (auto& op : func.type.getHeapType().getSignature().params) {
      tracerParamTypes.push_back(op);
    }

    return Type(tracerParamTypes);
  }

  TracedFunctions parseArgument(const std::string& arg) {
    TracedFunctions tracedFunctions;

    for (const auto& definition : String::Split(arg, ",")) {
      if (definition.empty()) {
        // Empty definition, ignore.
        continue;
      }

      std::string originName, traceName;
      parseFunctionName(definition, originName, traceName);

      tracedFunctions[Name(originName)] = Name(traceName);
    }

    return tracedFunctions;
  }

  void parseFunctionName(const std::string& str,
                         std::string& originName,
                         std::string& traceName) {
    auto parts = String::Split(str, ":");
    switch (parts.size()) {
      case 1:
        originName = parts[0];
        traceName = "trace_" + originName;
        break;
      case 2:
        originName = parts[0];
        traceName = parts[1];
        break;
      default:
        Fatal() << "Failed to parse function name ('" << str
                << "'): expected format FUNCTION_TO_TRACE[:TRACER_NAME]";
    }
  }

  void addImport(Module* wasm, const Function& f, const Name& tracerName) {
    ImportInfo info(*wasm);

    if (!info.getImportedFunction(ENV, tracerName)) {
      auto import = Builder::makeFunction(
        tracerName,
        Type(Signature(getTracerParamsType(info, f), Type::none),
             NonNullable,
             Inexact),
        {});
      import->module = ENV;
      import->base = tracerName;
      wasm->addFunction(std::move(import));
    }
  }
};

Pass* createTraceCallsPass() { return new TraceCalls(); }

} // namespace wasm
