403 lines
12 KiB
C++
403 lines
12 KiB
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.
|
|
*/
|
|
|
|
#ifndef WABT_EMSCRIPTEN_HELPERS_H_
|
|
#define WABT_EMSCRIPTEN_HELPERS_H_
|
|
|
|
#include <cstddef>
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "wabt/apply-names.h"
|
|
#include "wabt/binary-reader-ir.h"
|
|
#include "wabt/binary-reader.h"
|
|
#include "wabt/binary-writer-spec.h"
|
|
#include "wabt/binary-writer.h"
|
|
#include "wabt/common.h"
|
|
#include "wabt/error-formatter.h"
|
|
#include "wabt/feature.h"
|
|
#include "wabt/filenames.h"
|
|
#include "wabt/generate-names.h"
|
|
#include "wabt/ir.h"
|
|
#include "wabt/stream.h"
|
|
#include "wabt/validator.h"
|
|
#include "wabt/wast-lexer.h"
|
|
#include "wabt/wast-parser.h"
|
|
#include "wabt/wat-writer.h"
|
|
|
|
using WabtOutputBufferPtr = std::unique_ptr<wabt::OutputBuffer>;
|
|
using WabtFilenameOutputBufferPair =
|
|
std::pair<std::string, WabtOutputBufferPtr>;
|
|
|
|
struct WabtParseWatResult {
|
|
wabt::Result result;
|
|
std::unique_ptr<wabt::Module> module;
|
|
};
|
|
|
|
struct WabtReadBinaryResult {
|
|
wabt::Result result;
|
|
std::unique_ptr<wabt::Module> module;
|
|
};
|
|
|
|
struct WabtWriteModuleResult {
|
|
wabt::Result result;
|
|
WabtOutputBufferPtr buffer;
|
|
WabtOutputBufferPtr log_buffer;
|
|
};
|
|
|
|
struct WabtWriteScriptResult {
|
|
wabt::Result result;
|
|
WabtOutputBufferPtr json_buffer;
|
|
WabtOutputBufferPtr log_buffer;
|
|
std::vector<WabtFilenameOutputBufferPair> module_buffers;
|
|
};
|
|
|
|
struct WabtParseWastResult {
|
|
wabt::Result result;
|
|
std::unique_ptr<wabt::Script> script;
|
|
};
|
|
|
|
extern "C" {
|
|
|
|
wabt::Features* wabt_new_features(void) {
|
|
return new wabt::Features();
|
|
}
|
|
|
|
void wabt_destroy_features(wabt::Features* f) {
|
|
delete f;
|
|
}
|
|
|
|
#define WABT_FEATURE(variable, flag, default_, help) \
|
|
bool wabt_##variable##_enabled(wabt::Features* f) { \
|
|
return f->variable##_enabled(); \
|
|
} \
|
|
void wabt_set_##variable##_enabled(wabt::Features* f, int enabled) { \
|
|
f->set_##variable##_enabled(enabled); \
|
|
}
|
|
#include "wabt/feature.def"
|
|
#undef WABT_FEATURE
|
|
|
|
wabt::WastLexer* wabt_new_wast_buffer_lexer(const char* filename,
|
|
const void* data,
|
|
size_t size,
|
|
wabt::Errors* errors) {
|
|
std::unique_ptr<wabt::WastLexer> lexer =
|
|
wabt::WastLexer::CreateBufferLexer(filename, data, size, errors);
|
|
return lexer.release();
|
|
}
|
|
|
|
WabtParseWatResult* wabt_parse_wat(wabt::WastLexer* lexer,
|
|
wabt::Features* features,
|
|
wabt::Errors* errors) {
|
|
wabt::WastParseOptions options(*features);
|
|
WabtParseWatResult* result = new WabtParseWatResult();
|
|
std::unique_ptr<wabt::Module> module;
|
|
result->result = wabt::ParseWatModule(lexer, &module, errors, &options);
|
|
result->module = std::move(module);
|
|
return result;
|
|
}
|
|
|
|
WabtParseWastResult* wabt_parse_wast(wabt::WastLexer* lexer,
|
|
wabt::Features* features,
|
|
wabt::Errors* errors) {
|
|
wabt::WastParseOptions options(*features);
|
|
WabtParseWastResult* result = new WabtParseWastResult();
|
|
std::unique_ptr<wabt::Script> script;
|
|
result->result = wabt::ParseWastScript(lexer, &script, errors, &options);
|
|
result->script = std::move(script);
|
|
return result;
|
|
}
|
|
|
|
WabtReadBinaryResult* wabt_read_binary(const void* data,
|
|
size_t size,
|
|
int read_debug_names,
|
|
wabt::Features* features,
|
|
wabt::Errors* errors) {
|
|
wabt::ReadBinaryOptions options;
|
|
options.features = *features;
|
|
options.read_debug_names = read_debug_names;
|
|
|
|
WabtReadBinaryResult* result = new WabtReadBinaryResult();
|
|
wabt::Module* module = new wabt::Module();
|
|
// TODO(binji): Pass through from wabt_read_binary parameter.
|
|
const char* filename = "<binary>";
|
|
result->result =
|
|
wabt::ReadBinaryIr(filename, data, size, options, errors, module);
|
|
result->module.reset(module);
|
|
return result;
|
|
}
|
|
|
|
wabt::Result::Enum wabt_validate_module(wabt::Module* module,
|
|
wabt::Features* features,
|
|
wabt::Errors* errors) {
|
|
wabt::ValidateOptions options;
|
|
options.features = *features;
|
|
return ValidateModule(module, errors, options);
|
|
}
|
|
|
|
wabt::Result::Enum wabt_validate_script(wabt::Script* script,
|
|
wabt::Features* features,
|
|
wabt::Errors* errors) {
|
|
wabt::ValidateOptions options;
|
|
options.features = *features;
|
|
return ValidateScript(script, errors, options);
|
|
}
|
|
|
|
WabtWriteScriptResult* wabt_write_binary_spec_script(
|
|
wabt::Script* script,
|
|
const char* source_filename,
|
|
const char* out_filename,
|
|
int log,
|
|
int canonicalize_lebs,
|
|
int relocatable,
|
|
int write_debug_names) {
|
|
wabt::MemoryStream log_stream;
|
|
wabt::MemoryStream* log_stream_p = log ? &log_stream : nullptr;
|
|
|
|
wabt::WriteBinaryOptions options;
|
|
options.canonicalize_lebs = canonicalize_lebs;
|
|
options.relocatable = relocatable;
|
|
options.write_debug_names = write_debug_names;
|
|
|
|
std::vector<wabt::FilenameMemoryStreamPair> module_streams;
|
|
wabt::MemoryStream json_stream(log_stream_p);
|
|
|
|
std::string module_filename_noext(
|
|
wabt::StripExtension(out_filename ? out_filename : source_filename));
|
|
|
|
WabtWriteScriptResult* result = new WabtWriteScriptResult();
|
|
result->result = WriteBinarySpecScript(&json_stream, script, source_filename,
|
|
module_filename_noext, options,
|
|
&module_streams, log_stream_p);
|
|
|
|
if (result->result == wabt::Result::Ok) {
|
|
result->json_buffer = json_stream.ReleaseOutputBuffer();
|
|
result->log_buffer = log ? log_stream.ReleaseOutputBuffer() : nullptr;
|
|
std::transform(module_streams.begin(), module_streams.end(),
|
|
std::back_inserter(result->module_buffers),
|
|
[](wabt::FilenameMemoryStreamPair& pair) {
|
|
return WabtFilenameOutputBufferPair(
|
|
pair.filename, pair.stream->ReleaseOutputBuffer());
|
|
});
|
|
}
|
|
return result;
|
|
}
|
|
|
|
wabt::Result::Enum wabt_apply_names_module(wabt::Module* module) {
|
|
return ApplyNames(module);
|
|
}
|
|
|
|
wabt::Result::Enum wabt_generate_names_module(wabt::Module* module) {
|
|
return GenerateNames(module);
|
|
}
|
|
|
|
WabtWriteModuleResult* wabt_write_binary_module(wabt::Module* module,
|
|
int log,
|
|
int canonicalize_lebs,
|
|
int relocatable,
|
|
int write_debug_names) {
|
|
wabt::MemoryStream log_stream;
|
|
wabt::WriteBinaryOptions options;
|
|
options.canonicalize_lebs = canonicalize_lebs;
|
|
options.relocatable = relocatable;
|
|
options.write_debug_names = write_debug_names;
|
|
|
|
wabt::MemoryStream stream(log ? &log_stream : nullptr);
|
|
WabtWriteModuleResult* result = new WabtWriteModuleResult();
|
|
result->result = WriteBinaryModule(&stream, module, options);
|
|
if (result->result == wabt::Result::Ok) {
|
|
result->buffer = stream.ReleaseOutputBuffer();
|
|
result->log_buffer = log ? log_stream.ReleaseOutputBuffer() : nullptr;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
WabtWriteModuleResult* wabt_write_text_module(wabt::Module* module,
|
|
int fold_exprs,
|
|
int inline_export) {
|
|
wabt::WriteWatOptions options;
|
|
options.fold_exprs = fold_exprs;
|
|
options.inline_export = inline_export;
|
|
|
|
wabt::MemoryStream stream;
|
|
WabtWriteModuleResult* result = new WabtWriteModuleResult();
|
|
result->result = WriteWat(&stream, module, options);
|
|
if (result->result == wabt::Result::Ok) {
|
|
result->buffer = stream.ReleaseOutputBuffer();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void wabt_destroy_module(wabt::Module* module) {
|
|
delete module;
|
|
}
|
|
|
|
void wabt_destroy_wast_lexer(wabt::WastLexer* lexer) {
|
|
delete lexer;
|
|
}
|
|
|
|
// Errors
|
|
wabt::Errors* wabt_new_errors(void) {
|
|
return new wabt::Errors();
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_format_text_errors(wabt::Errors* errors,
|
|
wabt::WastLexer* lexer) {
|
|
auto line_finder = lexer->MakeLineFinder();
|
|
std::string string_result = FormatErrorsToString(
|
|
*errors, wabt::Location::Type::Text, line_finder.get());
|
|
|
|
wabt::OutputBuffer* result = new wabt::OutputBuffer();
|
|
std::copy(string_result.begin(), string_result.end(),
|
|
std::back_inserter(result->data));
|
|
return result;
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_format_binary_errors(wabt::Errors* errors) {
|
|
std::string string_result =
|
|
FormatErrorsToString(*errors, wabt::Location::Type::Binary);
|
|
|
|
wabt::OutputBuffer* result = new wabt::OutputBuffer();
|
|
std::copy(string_result.begin(), string_result.end(),
|
|
std::back_inserter(result->data));
|
|
return result;
|
|
}
|
|
|
|
void wabt_destroy_errors(wabt::Errors* errors) {
|
|
delete errors;
|
|
}
|
|
|
|
// WabtParseWatResult
|
|
wabt::Result::Enum wabt_parse_wat_result_get_result(
|
|
WabtParseWatResult* result) {
|
|
return result->result;
|
|
}
|
|
|
|
wabt::Module* wabt_parse_wat_result_release_module(WabtParseWatResult* result) {
|
|
return result->module.release();
|
|
}
|
|
|
|
void wabt_destroy_parse_wat_result(WabtParseWatResult* result) {
|
|
delete result;
|
|
}
|
|
|
|
// WabtParseWastResult
|
|
wabt::Result::Enum wabt_parse_wast_result_get_result(
|
|
WabtParseWastResult* result) {
|
|
return result->result;
|
|
}
|
|
|
|
wabt::Script* wabt_parse_wast_result_release_module(
|
|
WabtParseWastResult* result) {
|
|
return result->script.release();
|
|
}
|
|
|
|
void wabt_destroy_parse_wast_result(WabtParseWastResult* result) {
|
|
delete result;
|
|
}
|
|
|
|
// WabtReadBinaryResult
|
|
wabt::Result::Enum wabt_read_binary_result_get_result(
|
|
WabtReadBinaryResult* result) {
|
|
return result->result;
|
|
}
|
|
|
|
wabt::Module* wabt_read_binary_result_release_module(
|
|
WabtReadBinaryResult* result) {
|
|
return result->module.release();
|
|
}
|
|
|
|
void wabt_destroy_read_binary_result(WabtReadBinaryResult* result) {
|
|
delete result;
|
|
}
|
|
|
|
// WabtWriteModuleResult
|
|
wabt::Result::Enum wabt_write_module_result_get_result(
|
|
WabtWriteModuleResult* result) {
|
|
return result->result;
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_write_module_result_release_output_buffer(
|
|
WabtWriteModuleResult* result) {
|
|
return result->buffer.release();
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_write_module_result_release_log_output_buffer(
|
|
WabtWriteModuleResult* result) {
|
|
return result->log_buffer.release();
|
|
}
|
|
|
|
void wabt_destroy_write_module_result(WabtWriteModuleResult* result) {
|
|
delete result;
|
|
}
|
|
|
|
// WabtWriteScriptResult
|
|
wabt::Result::Enum wabt_write_script_result_get_result(
|
|
WabtWriteScriptResult* result) {
|
|
return result->result;
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_write_script_result_release_json_output_buffer(
|
|
WabtWriteScriptResult* result) {
|
|
return result->json_buffer.release();
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_write_script_result_release_log_output_buffer(
|
|
WabtWriteScriptResult* result) {
|
|
return result->log_buffer.release();
|
|
}
|
|
|
|
size_t wabt_write_script_result_get_module_count(
|
|
WabtWriteScriptResult* result) {
|
|
return result->module_buffers.size();
|
|
}
|
|
|
|
const char* wabt_write_script_result_get_module_filename(
|
|
WabtWriteScriptResult* result,
|
|
size_t index) {
|
|
return result->module_buffers[index].first.c_str();
|
|
}
|
|
|
|
wabt::OutputBuffer* wabt_write_script_result_release_module_output_buffer(
|
|
WabtWriteScriptResult* result,
|
|
size_t index) {
|
|
return result->module_buffers[index].second.release();
|
|
}
|
|
|
|
void wabt_destroy_write_script_result(WabtWriteScriptResult* result) {
|
|
delete result;
|
|
}
|
|
|
|
// wabt::OutputBuffer*
|
|
const void* wabt_output_buffer_get_data(wabt::OutputBuffer* output_buffer) {
|
|
return output_buffer->data.data();
|
|
}
|
|
|
|
size_t wabt_output_buffer_get_size(wabt::OutputBuffer* output_buffer) {
|
|
return output_buffer->data.size();
|
|
}
|
|
|
|
void wabt_destroy_output_buffer(wabt::OutputBuffer* output_buffer) {
|
|
delete output_buffer;
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
#endif /* WABT_EMSCRIPTEN_HELPERS_H_ */
|