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

//
// Emit a C  wrapper file that can run the wasm after it is compiled with
// wasm2c, useful for fuzzing.
//

#include <sstream>
#include <string>

#include "wasm.h"

namespace wasm {

// Mangle a name in (hopefully) exactly the same way wasm2c does.
inline std::string wasm2cMangle(Name name, Signature sig) {
  const char escapePrefix = 'Z';
  std::string mangled = "Z_";
  for (unsigned char c : name.str) {
    if ((isalnum(c) && c != escapePrefix) || c == '_') {
      // This character is ok to emit as it is.
      mangled += c;
    } else {
      // This must be escaped, as prefix + hex character code.
      mangled += escapePrefix;
      std::stringstream ss;
      ss << std::hex << std::uppercase << unsigned(c);
      mangled += ss.str();
    }
  }

  // Emit the result and params.
  mangled += "Z_";

  auto wasm2cSignature = [](Type type) {
    TODO_SINGLE_COMPOUND(type);
    switch (type.getBasic()) {
      case Type::none:
        return 'v';
      case Type::i32:
        return 'i';
      case Type::i64:
        return 'j';
      case Type::f32:
        return 'f';
      case Type::f64:
        return 'd';
      default:
        Fatal() << "unhandled wasm2c wrapper signature type: " << type;
    }
  };

  mangled += wasm2cSignature(sig.results);
  if (sig.params.isTuple()) {
    for (const auto& param : sig.params) {
      mangled += wasm2cSignature(param);
    }
  } else {
    mangled += wasm2cSignature(sig.params);
  }

  return mangled;
}

inline std::string generateWasm2CWrapper(Module& wasm) {
  // First, emit implementations of the wasm's imports so that the wasm2c code
  // can call them. The names use wasm2c's name mangling.
  std::string ret = R"(
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

#include "wasm-rt-impl.h"
#include "wasm.h"

void _Z_fuzzingZ2DsupportZ_logZ2Di32Z_vi(u32 x) {
  printf("[LoggingExternalInterface logging %d]\n", x);
}
void (*Z_fuzzingZ2DsupportZ_logZ2Di32Z_vi)(u32) = _Z_fuzzingZ2DsupportZ_logZ2Di32Z_vi;

void _Z_fuzzingZ2DsupportZ_logZ2Di64Z_vj(u64 x) {
  printf("[LoggingExternalInterface logging %" PRId64 "]\n", (int64_t)x);
}
void (*Z_fuzzingZ2DsupportZ_logZ2Di64Z_vj)(u64) = _Z_fuzzingZ2DsupportZ_logZ2Di64Z_vj;

void _Z_fuzzingZ2DsupportZ_logZ2Di64Z_vii(u32 x, u32 y) {
  printf("[LoggingExternalInterface logging %d %d]\n", x, y);
}
void (*Z_fuzzingZ2DsupportZ_logZ2Di64Z_vii)(u32, u32) = _Z_fuzzingZ2DsupportZ_logZ2Di64Z_vii;

void _Z_fuzzingZ2DsupportZ_logZ2Df32Z_vf(f32 x) {
  printf("[LoggingExternalInterface logging %.17e]\n", x);
}
void (*Z_fuzzingZ2DsupportZ_logZ2Df32Z_vf)(f32) = _Z_fuzzingZ2DsupportZ_logZ2Df32Z_vf;

void _Z_fuzzingZ2DsupportZ_logZ2Df64Z_vd(f64 x) {
  printf("[LoggingExternalInterface logging %.17le]\n", x);
}
void (*Z_fuzzingZ2DsupportZ_logZ2Df64Z_vd)(f64) = _Z_fuzzingZ2DsupportZ_logZ2Df64Z_vd;

// Miscellaneous imports

u32 tempRet0 = 0;

void _Z_envZ_setTempRet0Z_vi(u32 x) {
  tempRet0 = x;
}
void (*Z_envZ_setTempRet0Z_vi)(u32) = _Z_envZ_setTempRet0Z_vi;

u32 _Z_envZ_getTempRet0Z_iv(void) {
  return tempRet0;
}
u32 (*Z_envZ_getTempRet0Z_iv)(void) = _Z_envZ_getTempRet0Z_iv;

// Main

int main(int argc, char** argv) {
  init();

  // We go through each export and call it, in turn. Note that we use a loop
  // so we can do all this with a single setjmp. A setjmp is needed to handle
  // wasm traps, and emitting a single one helps compilation speed into wasm as
  // compile times are O(size * num_setjmps).
  for (size_t curr = 0;; curr++) {
  )";
  ret += R"(
    // Prepare to call the export, so we can catch traps.
    if (WASM_RT_SETJMP(g_jmp_buf) != 0) {
      puts("exception!");
    } else {
      // Call the proper export.
      switch(curr) {
)";

  // For each function export in the wasm, emit code to call it and log its
  // result, similar to the other wrappers.
  size_t functionExportIndex = 0;

  for (auto& exp : wasm.exports) {
    if (exp->kind != ExternalKind::Function) {
      continue;
    }

    ret += "        case " + std::to_string(functionExportIndex++) + ":\n";

    auto* func = wasm.getFunction(*exp->getInternalName());

    ret += std::string("          puts(\"[fuzz-exec] calling ") +
           exp->name.toString() + "\");\n";
    auto result = func->getResults();

    // Emit the call itself.
    ret += "            ";
    if (result != Type::none) {
      ret += std::string("printf(\"[fuzz-exec] note result: ") +
             exp->name.toString() + " => ";
      TODO_SINGLE_COMPOUND(result);
      switch (result.getBasic()) {
        case Type::i32:
          ret += "%d\\n\", ";
          break;
        case Type::i64:
          ret += "%\" PRId64 \"\\n\", (int64_t)";
          break;
        case Type::f32:
          ret += "%.17e\\n\", ";
          break;
        case Type::f64:
          ret += "%.17le\\n\", ";
          break;
        default:
          Fatal() << "unhandled wasm2c wrapper result type: " << result;
      }
    }

    // Call the export.
    ret += "(*";

    // Emit the callee's name with wasm2c name mangling.
    ret += wasm2cMangle(exp->name, func->getSig());

    ret += ")(";

    // Emit the parameters (all 0s, like the other wrappers).
    bool first = true;
    for ([[maybe_unused]] const auto& param : func->getParams()) {
      if (!first) {
        ret += ", ";
      }
      ret += "0";
      first = false;
    }
    if (result != Type::none) {
      ret += ")";
    }
    ret += ");\n";

    // Break from the big switch.
    ret += "          break;\n";
  }

  ret += R"(        default:
          return 0; // All done.
      }
    }
  }
  return 0;
}
)";

  return ret;
}

} // namespace wasm
