reflect.cc 3.85 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cinttypes>

#include "wasm.hh"


auto operator<<(std::ostream& out, wasm::Mutability mut) -> std::ostream& {
  switch (mut) {
    case wasm::VAR: return out << "var";
    case wasm::CONST: return out << "const";
  }
  return out;
}

auto operator<<(std::ostream& out, wasm::Limits limits) -> std::ostream& {
  out << limits.min;
  if (limits.max < wasm::Limits(0).max) out << " " << limits.max;
  return out;
}

auto operator<<(std::ostream& out, const wasm::ValType& type) -> std::ostream& {
  switch (type.kind()) {
    case wasm::I32: return out << "i32";
    case wasm::I64: return out << "i64";
    case wasm::F32: return out << "f32";
    case wasm::F64: return out << "f64";
    case wasm::ANYREF: return out << "anyref";
    case wasm::FUNCREF: return out << "funcref";
  }
  return out;
}

36
auto operator<<(std::ostream& out, const wasm::ownvec<wasm::ValType>& types) -> std::ostream& {
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  bool first = true;
  for (size_t i = 0; i < types.size(); ++i) {
    if (first) {
      first = false;
    } else {
      out << " ";
    }
    out << *types[i].get();
  }
  return out;
}

auto operator<<(std::ostream& out, const wasm::ExternType& type) -> std::ostream& {
  switch (type.kind()) {
    case wasm::EXTERN_FUNC: {
      out << "func " << type.func()->params() << " -> " << type.func()->results();
    } break;
    case wasm::EXTERN_GLOBAL: {
      out << "global " << type.global()->mutability() << " " << *type.global()->content();
    } break;
    case wasm::EXTERN_TABLE: {
      out << "table " << type.table()->limits() << " " << *type.table()->element();
    } break;
    case wasm::EXTERN_MEMORY: {
      out << "memory " << type.memory()->limits();
    } break;
  }
  return out;
}

auto operator<<(std::ostream& out, const wasm::Name& name) -> std::ostream& {
  out << "\"" << std::string(name.get(), name.size()) << "\"";
  return out;
}


void run() {
  // Initialize.
  std::cout << "Initializing..." << std::endl;
  auto engine = wasm::Engine::make();
  auto store_ = wasm::Store::make(engine.get());
  auto store = store_.get();

  // Load binary.
  std::cout << "Loading binary..." << std::endl;
  std::ifstream file("reflect.wasm");
  file.seekg(0, std::ios_base::end);
  auto file_size = file.tellg();
  file.seekg(0);
  auto binary = wasm::vec<byte_t>::make_uninitialized(file_size);
  file.read(binary.get(), file_size);
  file.close();
  if (file.fail()) {
    std::cout << "> Error loading module!" << std::endl;
91
    exit(1);
92 93 94 95 96 97 98
  }

  // Compile.
  std::cout << "Compiling module..." << std::endl;
  auto module = wasm::Module::make(store, binary);
  if (!module) {
    std::cout << "> Error compiling module!" << std::endl;
99
    exit(1);
100 101 102 103 104 105 106
  }

  // Instantiate.
  std::cout << "Instantiating module..." << std::endl;
  auto instance = wasm::Instance::make(store, module.get(), nullptr);
  if (!instance) {
    std::cout << "> Error instantiating module!" << std::endl;
107
    exit(1);
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
  }

  // Extract exports.
  std::cout << "Extracting export..." << std::endl;
  auto export_types = module->exports();
  auto exports = instance->exports();
  assert(exports.size() == export_types.size());

  for (size_t i = 0; i < exports.size(); ++i) {
    assert(exports[i]->kind() == export_types[i]->type()->kind());
    std::cout << "> export " << i << " " << export_types[i]->name() << std::endl;
    std::cout << ">> initial: " << *export_types[i]->type() << std::endl;
    std::cout << ">> current: " << *exports[i]->type() << std::endl;
    if (exports[i]->kind() == wasm::EXTERN_FUNC) {
      auto func = exports[i]->func();
      std::cout << ">> in-arity: " << func->param_arity();
      std::cout << ", out-arity: " << func->result_arity() << std::endl;
    }
  }

  // Shut down.
  std::cout << "Shutting down..." << std::endl;
}


int main(int argc, const char* argv[]) {
  run();
  std::cout << "Done." << std::endl;
  return 0;
}