Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/wasm2c/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 19 kB image not shown  

Quelle  binary-writer-spec.cc   Sprache: C

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


#include "wabt/binary-writer-spec.h"

#include <cassert>
#include <cinttypes>
#include <string_view>

#include "wabt/config.h"

#include "wabt/binary-writer.h"
#include "wabt/binary.h"
#include "wabt/cast.h"
#include "wabt/filenames.h"
#include "wabt/ir.h"
#include "wabt/literal.h"
#include "wabt/stream.h"

namespace wabt {

namespace {

class BinaryWriterSpec {
 public:
  BinaryWriterSpec(Stream* json_stream,
                   WriteBinarySpecStreamFactory module_stream_factory,
                   std::string_view source_filename,
                   std::string_view module_filename_noext,
                   const WriteBinaryOptions& options);

  Result WriteScript(const Script& script);

 private:
  std::string GetModuleFilename(const char* extension);
  void WriteString(const char* s);
  void WriteKey(const char* key);
  void WriteSeparator();
  void WriteEscapedString(std::string_view);
  void WriteCommandType(const Command& command);
  void WriteLocation(const Location& loc);
  void WriteVar(const Var& var);
  void WriteTypeObject(Type type);
  void WriteF32(uint32_t, ExpectedNan);
  void WriteF64(uint64_t, ExpectedNan);
  void WriteRefBits(uintptr_t ref_bits);
  void WriteConst(const Const& const_);
  void WriteConstVector(const ConstVector& consts);
  void WriteAction(const Action& action);
  void WriteActionResultType(const Action& action);
  void WriteModule(std::string_view filename, const Module& module);
  void WriteScriptModule(std::string_view filename,
                         const ScriptModule& script_module);
  void WriteInvalidModule(const ScriptModule& module, std::string_view text);
  void WriteCommands();

  const Script* script_ = nullptr;
  Stream* json_stream_ = nullptr;
  WriteBinarySpecStreamFactory module_stream_factory_;
  std::string source_filename_;
  std::string module_filename_noext_;
  const WriteBinaryOptions& options_;
  Result result_ = Result::Ok;
  size_t num_modules_ = 0;
};

BinaryWriterSpec::BinaryWriterSpec(
    Stream* json_stream,
    WriteBinarySpecStreamFactory module_stream_factory,
    std::string_view source_filename,
    std::string_view module_filename_noext,
    const WriteBinaryOptions& options)
    : json_stream_(json_stream),
      module_stream_factory_(module_stream_factory),
      source_filename_(source_filename),
      module_filename_noext_(module_filename_noext),
      options_(options) {}

std::string BinaryWriterSpec::GetModuleFilename(const char* extension) {
  std::string result = module_filename_noext_;
  result += '.';
  result += std::to_string(num_modules_);
  result += extension;
  ConvertBackslashToSlash(&result);
  return result;
}

void BinaryWriterSpec::WriteString(const char* s) {
  json_stream_->Writef("\"%s\"", s);
}

void BinaryWriterSpec::WriteKey(const char* key) {
  json_stream_->Writef("\"%s\": ", key);
}

void BinaryWriterSpec::WriteSeparator() {
  json_stream_->Writef(", ");
}

void BinaryWriterSpec::WriteEscapedString(std::string_view s) {
  json_stream_->WriteChar('"');
  for (size_t i = 0; i < s.length(); ++i) {
    uint8_t c = s[i];
    if (c < 0x20 || c == '\\' || c == '"') {
      json_stream_->Writef("\\u%04x", c);
    } else {
      json_stream_->WriteChar(c);
    }
  }
  json_stream_->WriteChar('"');
}

void BinaryWriterSpec::WriteCommandType(const Command& command) {
  static const char* s_command_names[] = {
      "module",
      "module",
      "action",
      "register",
      "assert_malformed",
      "assert_invalid",
      "assert_unlinkable",
      "assert_uninstantiable",
      "assert_return",
      "assert_trap",
      "assert_exhaustion",
      "assert_exception",
  };
  WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(s_command_names) == kCommandTypeCount);

  WriteKey("type");
  assert(s_command_names[static_cast<size_t>(command.type)]);
  WriteString(s_command_names[static_cast<size_t>(command.type)]);
}

void BinaryWriterSpec::WriteLocation(const Location& loc) {
  WriteKey("line");
  json_stream_->Writef("%d", loc.line);
}

void BinaryWriterSpec::WriteVar(const Var& var) {
  if (var.is_index()) {
    json_stream_->Writef("\"%" PRIindex "\"", var.index());
  } else {
    WriteEscapedString(var.name());
  }
}

void BinaryWriterSpec::WriteTypeObject(Type type) {
  json_stream_->Writef("{");
  WriteKey("type");
  WriteString(type.GetName().c_str());
  json_stream_->Writef("}");
}

void BinaryWriterSpec::WriteF32(uint32_t f32_bits, ExpectedNan expected) {
  switch (expected) {
    case ExpectedNan::None:
      json_stream_->Writef("\"%u\"", f32_bits);
      break;

    case ExpectedNan::Arithmetic:
      WriteString("nan:arithmetic");
      break;

    case ExpectedNan::Canonical:
      WriteString("nan:canonical");
      break;
  }
}

void BinaryWriterSpec::WriteF64(uint64_t f64_bits, ExpectedNan expected) {
  switch (expected) {
    case ExpectedNan::None:
      json_stream_->Writef("\"%" PRIu64 "\"", f64_bits);
      break;

    case ExpectedNan::Arithmetic:
      WriteString("nan:arithmetic");
      break;

    case ExpectedNan::Canonical:
      WriteString("nan:canonical");
      break;
  }
}

void BinaryWriterSpec::WriteRefBits(uintptr_t ref_bits) {
  if (ref_bits == Const::kRefNullBits) {
    json_stream_->Writef("\"null\"");
  } else {
    json_stream_->Writef("\"%" PRIuPTR "\"", ref_bits);
  }
}

void BinaryWriterSpec::WriteConst(const Const& const_) {
  json_stream_->Writef("{");
  WriteKey("type");

  /* Always write the values as strings, even though they may be representable
   * as JSON numbers. This way the formatting is consistent. */

  switch (const_.type()) {
    case Type::I32:
      WriteString("i32");
      WriteSeparator();
      WriteKey("value");
      json_stream_->Writef("\"%u\"", const_.u32());
      break;

    case Type::I64:
      WriteString("i64");
      WriteSeparator();
      WriteKey("value");
      json_stream_->Writef("\"%" PRIu64 "\"", const_.u64());
      break;

    case Type::F32:
      WriteString("f32");
      WriteSeparator();
      WriteKey("value");
      WriteF32(const_.f32_bits(), const_.expected_nan());
      break;

    case Type::F64:
      WriteString("f64");
      WriteSeparator();
      WriteKey("value");
      WriteF64(const_.f64_bits(), const_.expected_nan());
      break;

    case Type::FuncRef: {
      WriteString("funcref");
      WriteSeparator();
      WriteKey("value");
      WriteRefBits(const_.ref_bits());
      break;
    }

    case Type::ExternRef: {
      WriteString("externref");
      WriteSeparator();
      WriteKey("value");
      WriteRefBits(const_.ref_bits());
      break;
    }

    case Type::ExnRef: {
      WriteString("exnref");
      WriteSeparator();
      WriteKey("value");
      WriteRefBits(const_.ref_bits());
      break;
    }

    case Type::V128: {
      WriteString("v128");
      WriteSeparator();
      WriteKey("lane_type");
      WriteString(const_.lane_type().GetName().c_str());
      WriteSeparator();
      WriteKey("value");
      json_stream_->Writef("[");

      for (int lane = 0; lane < const_.lane_count(); ++lane) {
        switch (const_.lane_type()) {
          case Type::I8:
            json_stream_->Writef("\"%u\"", const_.v128_lane<uint8_t>(lane));
            break;

          case Type::I16:
            json_stream_->Writef("\"%u\"", const_.v128_lane<uint16_t>(lane));
            break;

          case Type::I32:
            json_stream_->Writef("\"%u\"", const_.v128_lane<uint32_t>(lane));
            break;

          case Type::I64:
            json_stream_->Writef("\"%" PRIu64 "\"",
                                 const_.v128_lane<uint64_t>(lane));
            break;

          case Type::F32:
            WriteF32(const_.v128_lane<uint32_t>(lane),
                     const_.expected_nan(lane));
            break;

          case Type::F64:
            WriteF64(const_.v128_lane<uint64_t>(lane),
                     const_.expected_nan(lane));
            break;

          default:
            WABT_UNREACHABLE;
        }

        if (lane != const_.lane_count() - 1) {
          WriteSeparator();
        }
      }

      json_stream_->Writef("]");

      break;
    }

    default:
      WABT_UNREACHABLE;
  }

  json_stream_->Writef("}");
}

void BinaryWriterSpec::WriteConstVector(const ConstVector& consts) {
  json_stream_->Writef("[");
  for (size_t i = 0; i < consts.size(); ++i) {
    const Const& const_ = consts[i];
    WriteConst(const_);
    if (i != consts.size() - 1) {
      WriteSeparator();
    }
  }
  json_stream_->Writef("]");
}

void BinaryWriterSpec::WriteAction(const Action& action) {
  WriteKey("action");
  json_stream_->Writef("{");
  WriteKey("type");
  if (action.type() == ActionType::Invoke) {
    WriteString("invoke");
  } else {
    assert(action.type() == ActionType::Get);
    WriteString("get");
  }
  WriteSeparator();
  if (action.module_var.is_name()) {
    WriteKey("module");
    WriteVar(action.module_var);
    WriteSeparator();
  }
  if (action.type() == ActionType::Invoke) {
    WriteKey("field");
    WriteEscapedString(action.name);
    WriteSeparator();
    WriteKey("args");
    WriteConstVector(cast<InvokeAction>(&action)->args);
  } else {
    WriteKey("field");
    WriteEscapedString(action.name);
  }
  json_stream_->Writef("}");
}

void BinaryWriterSpec::WriteActionResultType(const Action& action) {
  const Module* module = script_->GetModule(action.module_var);
  const Export* export_;
  json_stream_->Writef("[");
  switch (action.type()) {
    case ActionType::Invoke: {
      export_ = module->GetExport(action.name);
      assert(export_->kind == ExternalKind::Func);
      const Func* func = module->GetFunc(export_->var);
      Index num_results = func->GetNumResults();
      for (Index i = 0; i < num_results; ++i)
        WriteTypeObject(func->GetResultType(i));
      break;
    }

    case ActionType::Get: {
      export_ = module->GetExport(action.name);
      assert(export_->kind == ExternalKind::Global);
      const Global* global = module->GetGlobal(export_->var);
      WriteTypeObject(global->type);
      break;
    }
  }
  json_stream_->Writef("]");
}

void BinaryWriterSpec::WriteModule(std::string_view filename,
                                   const Module& module) {
  result_ |=
      WriteBinaryModule(module_stream_factory_(filename), &module, options_);
}

void BinaryWriterSpec::WriteScriptModule(std::string_view filename,
                                         const ScriptModule& script_module) {
  switch (script_module.type()) {
    case ScriptModuleType::Text:
      WriteModule(filename, cast<TextScriptModule>(&script_module)->module);
      break;

    case ScriptModuleType::Binary:
      module_stream_factory_(filename)->WriteData(
          cast<BinaryScriptModule>(&script_module)->data, "");
      break;

    case ScriptModuleType::Quoted:
      module_stream_factory_(filename)->WriteData(
          cast<QuotedScriptModule>(&script_module)->data, "");
      break;
  }
}

void BinaryWriterSpec::WriteInvalidModule(const ScriptModule& module,
                                          std::string_view text) {
  const char* extension = "";
  const char* module_type = "";
  switch (module.type()) {
    case ScriptModuleType::Text:
      extension = kWasmExtension;
      module_type = "binary";
      break;

    case ScriptModuleType::Binary:
      extension = kWasmExtension;
      module_type = "binary";
      break;

    case ScriptModuleType::Quoted:
      extension = kWatExtension;
      module_type = "text";
      break;
  }

  WriteLocation(module.location());
  WriteSeparator();
  std::string filename = GetModuleFilename(extension);
  WriteKey("filename");
  WriteEscapedString(GetBasename(filename));
  WriteSeparator();
  WriteKey("text");
  WriteEscapedString(text);
  WriteSeparator();
  WriteKey("module_type");
  WriteString(module_type);
  WriteScriptModule(filename, module);
}

void BinaryWriterSpec::WriteCommands() {
  json_stream_->Writef("{\"source_filename\": ");
  WriteEscapedString(source_filename_);
  json_stream_->Writef(",\n \"commands\": [\n");
  Index last_module_index = kInvalidIndex;
  for (size_t i = 0; i < script_->commands.size(); ++i) {
    const Command* command = script_->commands[i].get();

    if (i != 0) {
      WriteSeparator();
      json_stream_->Writef("\n");
    }

    json_stream_->Writef(" {");
    WriteCommandType(*command);
    WriteSeparator();

    switch (command->type) {
      case CommandType::Module: {
        const Module& module = cast<ModuleCommand>(command)->module;
        std::string filename = GetModuleFilename(kWasmExtension);
        WriteLocation(module.loc);
        WriteSeparator();
        if (!module.name.empty()) {
          WriteKey("name");
          WriteEscapedString(module.name);
          WriteSeparator();
        }
        WriteKey("filename");
        WriteEscapedString(GetBasename(filename));
        WriteModule(filename, module);
        num_modules_++;
        last_module_index = i;
        break;
      }

      case CommandType::ScriptModule: {
        auto* script_module_command = cast<ScriptModuleCommand>(command);
        const auto& module = script_module_command->module;
        std::string filename = GetModuleFilename(kWasmExtension);
        WriteLocation(module.loc);
        WriteSeparator();
        if (!module.name.empty()) {
          WriteKey("name");
          WriteEscapedString(module.name);
          WriteSeparator();
        }
        WriteKey("filename");
        WriteEscapedString(GetBasename(filename));
        WriteScriptModule(filename, *script_module_command->script_module);
        num_modules_++;
        last_module_index = i;
        break;
      }

      case CommandType::Action: {
        const Action& action = *cast<ActionCommand>(command)->action;
        WriteLocation(action.loc);
        WriteSeparator();
        WriteAction(action);
        WriteSeparator();
        WriteKey("expected");
        WriteActionResultType(action);
        break;
      }

      case CommandType::Register: {
        auto* register_command = cast<RegisterCommand>(command);
        const Var& var = register_command->var;
        WriteLocation(var.loc);
        WriteSeparator();
        if (var.is_name()) {
          WriteKey("name");
          WriteVar(var);
          WriteSeparator();
        } else {
          /* If we're not registering by name, then we should only be
           * registering the last module. */

          WABT_USE(last_module_index);
          assert(var.index() == last_module_index);
        }
        WriteKey("as");
        WriteEscapedString(register_command->module_name);
        break;
      }

      case CommandType::AssertMalformed: {
        auto* assert_malformed_command = cast<AssertMalformedCommand>(command);
        WriteInvalidModule(*assert_malformed_command->module,
                           assert_malformed_command->text);
        num_modules_++;
        break;
      }

      case CommandType::AssertInvalid: {
        auto* assert_invalid_command = cast<AssertInvalidCommand>(command);
        WriteInvalidModule(*assert_invalid_command->module,
                           assert_invalid_command->text);
        num_modules_++;
        break;
      }

      case CommandType::AssertUnlinkable: {
        auto* assert_unlinkable_command =
            cast<AssertUnlinkableCommand>(command);
        WriteInvalidModule(*assert_unlinkable_command->module,
                           assert_unlinkable_command->text);
        num_modules_++;
        break;
      }

      case CommandType::AssertUninstantiable: {
        auto* assert_uninstantiable_command =
            cast<AssertUninstantiableCommand>(command);
        WriteInvalidModule(*assert_uninstantiable_command->module,
                           assert_uninstantiable_command->text);
        num_modules_++;
        break;
      }

      case CommandType::AssertReturn: {
        auto* assert_return_command = cast<AssertReturnCommand>(command);
        WriteLocation(assert_return_command->action->loc);
        WriteSeparator();
        WriteAction(*assert_return_command->action);
        WriteSeparator();
        const Expectation* expectation = assert_return_command->expected.get();
        switch (expectation->type()) {
          case ExpectationType::Values:
            WriteKey("expected");
            break;

          case ExpectationType::Either:
            WriteKey("either");
            break;
        }
        WriteConstVector(expectation->expected);
        break;
      }

      case CommandType::AssertTrap: {
        auto* assert_trap_command = cast<AssertTrapCommand>(command);
        WriteLocation(assert_trap_command->action->loc);
        WriteSeparator();
        WriteAction(*assert_trap_command->action);
        WriteSeparator();
        WriteKey("text");
        WriteEscapedString(assert_trap_command->text);
        WriteSeparator();
        WriteKey("expected");
        WriteActionResultType(*assert_trap_command->action);
        break;
      }

      case CommandType::AssertExhaustion: {
        auto* assert_exhaustion_command =
            cast<AssertExhaustionCommand>(command);
        WriteLocation(assert_exhaustion_command->action->loc);
        WriteSeparator();
        WriteAction(*assert_exhaustion_command->action);
        WriteSeparator();
        WriteKey("text");
        WriteEscapedString(assert_exhaustion_command->text);
        WriteSeparator();
        WriteKey("expected");
        WriteActionResultType(*assert_exhaustion_command->action);
        break;
      }

      case CommandType::AssertException: {
        auto* assert_exception_command = cast<AssertExceptionCommand>(command);
        WriteLocation(assert_exception_command->action->loc);
        WriteSeparator();
        WriteAction(*assert_exception_command->action);
        WriteSeparator();
        WriteKey("expected");
        WriteActionResultType(*assert_exception_command->action);
        break;
      }
    }

    json_stream_->Writef("}");
  }
  json_stream_->Writef("]}\n");
}

Result BinaryWriterSpec::WriteScript(const Script& script) {
  script_ = &script;
  WriteCommands();
  return result_;
}

}  // end anonymous namespace

Result WriteBinarySpecScript(Stream* json_stream,
                             WriteBinarySpecStreamFactory module_stream_factory,
                             Script* script,
                             std::string_view source_filename,
                             std::string_view module_filename_noext,
                             const WriteBinaryOptions& options) {
  BinaryWriterSpec binary_writer_spec(json_stream, module_stream_factory,
                                      source_filename, module_filename_noext,
                                      options);
  return binary_writer_spec.WriteScript(*script);
}

Result WriteBinarySpecScript(
    Stream* json_stream,
    Script* script,
    std::string_view source_filename,
    std::string_view module_filename_noext,
    const WriteBinaryOptions& options,
    std::vector<FilenameMemoryStreamPair>* out_module_streams,
    Stream* log_stream) {
  WriteBinarySpecStreamFactory module_stream_factory =
      [&](std::string_view filename) {
        out_module_streams->emplace_back(
            filename, std::make_unique<MemoryStream>(log_stream));
        return out_module_streams->back().stream.get();
      };

  BinaryWriterSpec binary_writer_spec(json_stream, module_stream_factory,
                                      source_filename, module_filename_noext,
                                      options);
  return binary_writer_spec.WriteScript(*script);
}

}  // namespace wabt

Messung V0.5
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.