Bug 1843419 - Vendor in the most recent wasm2c release r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D183537
This commit is contained in:
Willy R. Vasquez 2023-07-14 06:35:17 +00:00
Родитель 4a15b82f13
Коммит 79d974a9e9
11 изменённых файлов: 332 добавлений и 294 удалений

Просмотреть файл

@ -66,6 +66,7 @@ HOST_SOURCES += [
"/third_party/wasm2c/src/c-writer.cc", "/third_party/wasm2c/src/c-writer.cc",
"/third_party/wasm2c/src/prebuilt/wasm2c_header_bottom.cc", "/third_party/wasm2c/src/prebuilt/wasm2c_header_bottom.cc",
"/third_party/wasm2c/src/prebuilt/wasm2c_header_top.cc", "/third_party/wasm2c/src/prebuilt/wasm2c_header_top.cc",
"/third_party/wasm2c/src/prebuilt/wasm2c_simd_source_declarations.cc",
"/third_party/wasm2c/src/prebuilt/wasm2c_source_declarations.cc", "/third_party/wasm2c/src/prebuilt/wasm2c_source_declarations.cc",
"/third_party/wasm2c/src/prebuilt/wasm2c_source_includes.cc", "/third_party/wasm2c/src/prebuilt/wasm2c_source_includes.cc",
"/third_party/wasm2c/src/tools/wasm2c.cc", "/third_party/wasm2c/src/tools/wasm2c.cc",

Просмотреть файл

@ -9,8 +9,8 @@ origin:
description: wasm2c fork used for rlbox sandboxing description: wasm2c fork used for rlbox sandboxing
url: https://github.com/WebAssembly/wabt url: https://github.com/WebAssembly/wabt
release: d24691ba62c371fb8dc2634956030e7102302174 (2023-05-05T23:57:24Z). release: 963f973469b45969ce198e0c86d3af316790a780 (2023-05-12T21:56:46Z).
revision: d24691ba62c371fb8dc2634956030e7102302174 revision: 963f973469b45969ce198e0c86d3af316790a780
license: Apache-2.0 license: Apache-2.0
license-file: LICENSE license-file: LICENSE

2
third_party/wasm2c/include/wabt/c-writer.h поставляемый
Просмотреть файл

@ -29,8 +29,6 @@ class Stream;
struct WriteCOptions { struct WriteCOptions {
std::string_view module_name; std::string_view module_name;
/* Set of wasm features enabled for wasm2c */
Features* features;
/* /*
* name_to_output_file_index takes const iterators to begin and end of a list * name_to_output_file_index takes const iterators to begin and end of a list
* of all functions in the module, number of imported functions, and number of * of all functions in the module, number of imported functions, and number of

8
third_party/wasm2c/include/wabt/ir.h поставляемый
Просмотреть файл

@ -1245,6 +1245,14 @@ struct Module {
BindingHash memory_bindings; BindingHash memory_bindings;
BindingHash data_segment_bindings; BindingHash data_segment_bindings;
BindingHash elem_segment_bindings; BindingHash elem_segment_bindings;
// For a subset of features, the BinaryReaderIR tracks whether they are
// actually used by the module. wasm2c (CWriter) uses this information to
// limit its output in some cases.
struct {
bool simd = false;
bool exceptions = false;
} features_used;
}; };
enum class ScriptModuleType { enum class ScriptModuleType {

18
third_party/wasm2c/src/binary-reader-ir.cc поставляемый
Просмотреть файл

@ -526,6 +526,15 @@ Result BinaryReaderIR::OnFuncType(Index index,
auto func_type = std::make_unique<FuncType>(); auto func_type = std::make_unique<FuncType>();
func_type->sig.param_types.assign(param_types, param_types + param_count); func_type->sig.param_types.assign(param_types, param_types + param_count);
func_type->sig.result_types.assign(result_types, result_types + result_count); func_type->sig.result_types.assign(result_types, result_types + result_count);
module_->features_used.simd |=
std::any_of(func_type->sig.param_types.begin(),
func_type->sig.param_types.end(),
[](auto x) { return x == Type::V128; }) ||
std::any_of(func_type->sig.result_types.begin(),
func_type->sig.result_types.end(),
[](auto x) { return x == Type::V128; });
field->type = std::move(func_type); field->type = std::move(func_type);
module_->AppendField(std::move(field)); module_->AppendField(std::move(field));
return Result::Ok; return Result::Ok;
@ -540,6 +549,7 @@ Result BinaryReaderIR::OnStructType(Index index,
for (Index i = 0; i < field_count; ++i) { for (Index i = 0; i < field_count; ++i) {
struct_type->fields[i].type = fields[i].type; struct_type->fields[i].type = fields[i].type;
struct_type->fields[i].mutable_ = fields[i].mutable_; struct_type->fields[i].mutable_ = fields[i].mutable_;
module_->features_used.simd |= (fields[i].type == Type::V128);
} }
field->type = std::move(struct_type); field->type = std::move(struct_type);
module_->AppendField(std::move(field)); module_->AppendField(std::move(field));
@ -551,6 +561,7 @@ Result BinaryReaderIR::OnArrayType(Index index, TypeMut type_mut) {
auto array_type = std::make_unique<ArrayType>(); auto array_type = std::make_unique<ArrayType>();
array_type->field.type = type_mut.type; array_type->field.type = type_mut.type;
array_type->field.mutable_ = type_mut.mutable_; array_type->field.mutable_ = type_mut.mutable_;
module_->features_used.simd |= (type_mut.type == Type::V128);
field->type = std::move(array_type); field->type = std::move(array_type);
module_->AppendField(std::move(field)); module_->AppendField(std::move(field));
return Result::Ok; return Result::Ok;
@ -620,6 +631,7 @@ Result BinaryReaderIR::OnImportGlobal(Index import_index,
import->global.mutable_ = mutable_; import->global.mutable_ = mutable_;
module_->AppendField( module_->AppendField(
std::make_unique<ImportModuleField>(std::move(import), GetLocation())); std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
module_->features_used.simd |= (type == Type::V128);
return Result::Ok; return Result::Ok;
} }
@ -634,6 +646,7 @@ Result BinaryReaderIR::OnImportTag(Index import_index,
SetFuncDeclaration(&import->tag.decl, Var(sig_index, GetLocation())); SetFuncDeclaration(&import->tag.decl, Var(sig_index, GetLocation()));
module_->AppendField( module_->AppendField(
std::make_unique<ImportModuleField>(std::move(import), GetLocation())); std::make_unique<ImportModuleField>(std::move(import), GetLocation()));
module_->features_used.exceptions = true;
return Result::Ok; return Result::Ok;
} }
@ -698,6 +711,7 @@ Result BinaryReaderIR::BeginGlobal(Index index, Type type, bool mutable_) {
global.type = type; global.type = type;
global.mutable_ = mutable_; global.mutable_ = mutable_;
module_->AppendField(std::move(field)); module_->AppendField(std::move(field));
module_->features_used.simd |= (type == Type::V128);
return Result::Ok; return Result::Ok;
} }
@ -763,6 +777,7 @@ Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) {
return Result::Error; return Result::Error;
} }
module_->features_used.simd |= (type == Type::V128);
return Result::Ok; return Result::Ok;
} }
@ -772,6 +787,7 @@ Result BinaryReaderIR::OnOpcode(Opcode opcode) {
if (metadata) { if (metadata) {
return AppendExpr(std::move(metadata)); return AppendExpr(std::move(metadata));
} }
module_->features_used.simd |= (opcode.GetResultType() == Type::V128);
return Result::Ok; return Result::Ok;
} }
@ -1143,6 +1159,7 @@ Result BinaryReaderIR::OnTryExpr(Type sig_type) {
ExprList* expr_list = &expr->block.exprs; ExprList* expr_list = &expr->block.exprs;
SetBlockDeclaration(&expr->block.decl, sig_type); SetBlockDeclaration(&expr->block.decl, sig_type);
CHECK_RESULT(AppendExpr(std::move(expr_ptr))); CHECK_RESULT(AppendExpr(std::move(expr_ptr)));
module_->features_used.exceptions = true;
return PushLabel(LabelType::Try, expr_list, expr); return PushLabel(LabelType::Try, expr_list, expr);
} }
@ -1647,6 +1664,7 @@ Result BinaryReaderIR::OnTagType(Index index, Index sig_index) {
Tag& tag = field->tag; Tag& tag = field->tag;
SetFuncDeclaration(&tag.decl, Var(sig_index, GetLocation())); SetFuncDeclaration(&tag.decl, Var(sig_index, GetLocation()));
module_->AppendField(std::move(field)); module_->AppendField(std::move(field));
module_->features_used.exceptions = true;
return Result::Ok; return Result::Ok;
} }

74
third_party/wasm2c/src/c-writer.cc поставляемый
Просмотреть файл

@ -42,6 +42,7 @@ extern const char* s_header_top;
extern const char* s_header_bottom; extern const char* s_header_bottom;
extern const char* s_source_includes; extern const char* s_source_includes;
extern const char* s_source_declarations; extern const char* s_source_declarations;
extern const char* s_simd_source_declarations;
namespace wabt { namespace wabt {
@ -368,7 +369,9 @@ class CWriter {
const std::string&); const std::string&);
void WriteCallIndirectFuncDeclaration(const FuncDeclaration&, void WriteCallIndirectFuncDeclaration(const FuncDeclaration&,
const std::string&); const std::string&);
void WriteFeatureMacros(); void ComputeSimdScope();
void WriteHeaderIncludes();
void WriteV128Decl();
void WriteModuleInstance(); void WriteModuleInstance();
void WriteGlobals(); void WriteGlobals();
void WriteGlobal(const Global&, const std::string&); void WriteGlobal(const Global&, const std::string&);
@ -484,6 +487,8 @@ class CWriter {
size_t, size_t,
size_t)> size_t)>
name_to_output_file_index_; name_to_output_file_index_;
bool simd_used_in_header_;
}; };
// TODO: if WABT begins supporting debug names for labels, // TODO: if WABT begins supporting debug names for labels,
@ -1411,7 +1416,14 @@ std::string CWriter::GenerateHeaderGuard() const {
void CWriter::WriteSourceTop() { void CWriter::WriteSourceTop() {
Write(s_source_includes); Write(s_source_includes);
Write(Newline(), "#include \"", header_name_, "\"", Newline()); Write(Newline(), "#include \"", header_name_, "\"", Newline());
Write(s_source_declarations); Write(s_source_declarations, Newline());
if (module_->features_used.simd) {
if (!simd_used_in_header_) {
WriteV128Decl();
}
Write(s_simd_source_declarations);
}
} }
void CWriter::WriteMultiCTop() { void CWriter::WriteMultiCTop() {
@ -1790,13 +1802,50 @@ void CWriter::WriteCallIndirectFuncDeclaration(const FuncDeclaration& decl,
Write(")"); Write(")");
} }
void CWriter::WriteFeatureMacros() { static bool func_uses_simd(const FuncSignature& sig) {
if (options_.features->exceptions_enabled()) { return std::any_of(sig.param_types.begin(), sig.param_types.end(),
Write("#define WASM_RT_ENABLE_EXCEPTION_HANDLING", Newline(), Newline()); [](auto x) { return x == Type::V128; }) ||
std::any_of(sig.result_types.begin(), sig.result_types.end(),
[](auto x) { return x == Type::V128; });
}
void CWriter::ComputeSimdScope() {
simd_used_in_header_ =
module_->features_used.simd &&
(std::any_of(module_->globals.begin(), module_->globals.end(),
[](const auto& x) { return x->type == Type::V128; }) ||
std::any_of(module_->imports.begin(), module_->imports.end(),
[](const auto& x) {
return x->kind() == ExternalKind::Func &&
func_uses_simd(cast<FuncImport>(x)->func.decl.sig);
}) ||
std::any_of(module_->exports.begin(), module_->exports.end(),
[&](const auto& x) {
return x->kind == ExternalKind::Func &&
func_uses_simd(module_->GetFunc(x->var)->decl.sig);
}));
}
void CWriter::WriteHeaderIncludes() {
Write("#include \"wasm-rt.h\"", Newline());
if (module_->features_used.exceptions) {
Write("#include \"wasm-rt-exceptions.h\"", Newline(), Newline());
} }
if (options_.features->simd_enabled()) {
Write("#define WASM_RT_ENABLE_SIMD", Newline(), Newline()); if (simd_used_in_header_) {
WriteV128Decl();
} }
Write(Newline());
}
void CWriter::WriteV128Decl() {
Write("#include <simde/wasm/simd128.h>", Newline(), Newline());
Write("#ifndef WASM_RT_SIMD_TYPE_DEFINED", Newline(),
"#define WASM_RT_SIMD_TYPE_DEFINED", Newline(),
"typedef simde_v128_t v128;", Newline(), "#endif", Newline(),
Newline());
} }
void CWriter::WriteModuleInstance() { void CWriter::WriteModuleInstance() {
@ -2837,7 +2886,9 @@ void CWriter::WriteTryCatch(const TryExpr& tryexpr) {
Write(CloseBrace(), Newline()); /* end of try-catch */ Write(CloseBrace(), Newline()); /* end of try-catch */
ResetTypeStack(mark); ResetTypeStack(mark);
Write(LabelDecl(label_stack_.back().name)); assert(!label_stack_.empty());
assert(label_stack_.back().name == tryexpr.block.label);
Write(LabelDecl(GetLocalName(tryexpr.block.label, true)));
PopLabel(); PopLabel();
PushTypes(tryexpr.block.decl.sig.result_types); PushTypes(tryexpr.block.decl.sig.result_types);
} }
@ -2939,7 +2990,9 @@ void CWriter::WriteTryDelegate(const TryExpr& tryexpr) {
PopTryCatch(); PopTryCatch();
ResetTypeStack(mark); ResetTypeStack(mark);
Write(LabelDecl(label_stack_.back().name)); assert(!label_stack_.empty());
assert(label_stack_.back().name == tryexpr.block.label);
Write(LabelDecl(GetLocalName(tryexpr.block.label, true)));
PopLabel(); PopLabel();
PushTypes(tryexpr.block.decl.sig.result_types); PushTypes(tryexpr.block.decl.sig.result_types);
} }
@ -5132,7 +5185,8 @@ void CWriter::WriteCHeader() {
Write("#ifndef ", guard, Newline()); Write("#ifndef ", guard, Newline());
Write("#define ", guard, Newline()); Write("#define ", guard, Newline());
Write(Newline()); Write(Newline());
WriteFeatureMacros(); ComputeSimdScope();
WriteHeaderIncludes();
Write(s_header_top); Write(s_header_top);
Write(Newline()); Write(Newline());
WriteModuleInstance(); WriteModuleInstance();

36
third_party/wasm2c/src/color.cc поставляемый
Просмотреть файл

@ -20,11 +20,9 @@
#include "wabt/common.h" #include "wabt/common.h"
#if _WIN32
#if HAVE_WIN32_VT100 #if HAVE_WIN32_VT100
#include <io.h> #include <io.h>
#include <windows.h> #include <windows.h>
#endif
#elif HAVE_UNISTD_H #elif HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -42,29 +40,23 @@ bool Color::SupportsColor(FILE* file) {
return atoi(force) != 0; return atoi(force) != 0;
} }
#if _WIN32
{
#if HAVE_WIN32_VT100 #if HAVE_WIN32_VT100
HANDLE handle;
if (file == stdout) { HANDLE handle;
handle = GetStdHandle(STD_OUTPUT_HANDLE); if (file == stdout) {
} else if (file == stderr) { handle = GetStdHandle(STD_OUTPUT_HANDLE);
handle = GetStdHandle(STD_ERROR_HANDLE); } else if (file == stderr) {
} else { handle = GetStdHandle(STD_ERROR_HANDLE);
return false; } else {
}
DWORD mode;
if (!_isatty(_fileno(file)) || !GetConsoleMode(handle, &mode) ||
!SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
return false;
}
return true;
#else
// TODO(binji): Support older Windows by using SetConsoleTextAttribute?
return false; return false;
#endif
} }
DWORD mode;
if (!_isatty(_fileno(file)) || !GetConsoleMode(handle, &mode) ||
!SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
return false;
}
return true;
// TODO(binji): Support older Windows by using SetConsoleTextAttribute?
#elif HAVE_UNISTD_H #elif HAVE_UNISTD_H

Просмотреть файл

@ -1,26 +1,7 @@
const char* s_header_top = R"w2c_template(#include <stdint.h> const char* s_header_top = R"w2c_template(#include <stdint.h>
)w2c_template" )w2c_template"
R"w2c_template( R"w2c_template(
#include "wasm-rt.h" #ifndef WASM_RT_CORE_TYPES_DEFINED
)w2c_template"
R"w2c_template(
#if defined(WASM_RT_ENABLE_EXCEPTION_HANDLING)
)w2c_template"
R"w2c_template(#include "wasm-rt-exceptions.h"
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(
#if defined(WASM_RT_ENABLE_SIMD)
)w2c_template"
R"w2c_template(#include "simde/wasm/simd128.h"
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(
/* TODO(binji): only use stdint.h types in header */
)w2c_template"
R"w2c_template(#ifndef WASM_RT_CORE_TYPES_DEFINED
)w2c_template" )w2c_template"
R"w2c_template(#define WASM_RT_CORE_TYPES_DEFINED R"w2c_template(#define WASM_RT_CORE_TYPES_DEFINED
)w2c_template" )w2c_template"
@ -44,17 +25,9 @@ R"w2c_template(typedef float f32;
)w2c_template" )w2c_template"
R"w2c_template(typedef double f64; R"w2c_template(typedef double f64;
)w2c_template" )w2c_template"
R"w2c_template(
#if defined(WASM_RT_ENABLE_SIMD)
)w2c_template"
R"w2c_template(typedef simde_v128_t v128;
)w2c_template"
R"w2c_template(#endif R"w2c_template(#endif
)w2c_template" )w2c_template"
R"w2c_template( R"w2c_template(
#endif
)w2c_template"
R"w2c_template(
#ifdef __cplusplus #ifdef __cplusplus
)w2c_template" )w2c_template"
R"w2c_template(extern "C" { R"w2c_template(extern "C" {

Просмотреть файл

@ -0,0 +1,224 @@
const char* s_simd_source_declarations = R"w2c_template(#ifdef __x86_64__
)w2c_template"
R"w2c_template(#define SIMD_FORCE_READ(var) wasm_asm("" ::"x"(var));
)w2c_template"
R"w2c_template(#else
)w2c_template"
R"w2c_template(#define SIMD_FORCE_READ(var)
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(// TODO: equivalent constraint for ARM and other architectures
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_LOAD_FUNC(name, func, t) \
)w2c_template"
R"w2c_template( static inline v128 name(wasm_rt_memory_t* mem, u64 addr) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( v128 result = func((v128*)&mem->data[addr]); \
)w2c_template"
R"w2c_template( SIMD_FORCE_READ(result); \
)w2c_template"
R"w2c_template( return result; \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_LOAD_LANE(name, func, t, lane) \
)w2c_template"
R"w2c_template( static inline v128 name(wasm_rt_memory_t* mem, u64 addr, v128 vec) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( v128 result = func((v128*)&mem->data[addr], vec, lane); \
)w2c_template"
R"w2c_template( SIMD_FORCE_READ(result); \
)w2c_template"
R"w2c_template( return result; \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_STORE(name, t) \
)w2c_template"
R"w2c_template( static inline void name(wasm_rt_memory_t* mem, u64 addr, v128 value) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( simde_wasm_v128_store((v128*)&mem->data[addr], value); \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_STORE_LANE(name, func, t, lane) \
)w2c_template"
R"w2c_template( static inline void name(wasm_rt_memory_t* mem, u64 addr, v128 value) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( func((v128*)&mem->data[addr], value, lane); \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
// clang-format off
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load, simde_wasm_v128_load, v128)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(v128_load8_splat, simde_wasm_v128_load8_splat, u8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load16_splat, simde_wasm_v128_load16_splat, u16)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load32_splat, simde_wasm_v128_load32_splat, u32)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load64_splat, simde_wasm_v128_load64_splat, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(i16x8_load8x8, simde_wasm_i16x8_load8x8, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u16x8_load8x8, simde_wasm_u16x8_load8x8, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(i32x4_load16x4, simde_wasm_i32x4_load16x4, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u32x4_load16x4, simde_wasm_u32x4_load16x4, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(i64x2_load32x2, simde_wasm_i64x2_load32x2, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u64x2_load32x2, simde_wasm_u64x2_load32x2, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(v128_load32_zero, simde_wasm_v128_load32_zero, u32)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load64_zero, simde_wasm_v128_load64_zero, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_LANE(v128_load8_lane0, simde_wasm_v128_load8_lane, u8, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane1, simde_wasm_v128_load8_lane, u8, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane2, simde_wasm_v128_load8_lane, u8, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane3, simde_wasm_v128_load8_lane, u8, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane4, simde_wasm_v128_load8_lane, u8, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane5, simde_wasm_v128_load8_lane, u8, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane6, simde_wasm_v128_load8_lane, u8, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane7, simde_wasm_v128_load8_lane, u8, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane8, simde_wasm_v128_load8_lane, u8, 8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane9, simde_wasm_v128_load8_lane, u8, 9)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane10, simde_wasm_v128_load8_lane, u8, 10)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane11, simde_wasm_v128_load8_lane, u8, 11)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane12, simde_wasm_v128_load8_lane, u8, 12)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane13, simde_wasm_v128_load8_lane, u8, 13)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane14, simde_wasm_v128_load8_lane, u8, 14)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane15, simde_wasm_v128_load8_lane, u8, 15)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane0, simde_wasm_v128_load16_lane, u16, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane1, simde_wasm_v128_load16_lane, u16, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane2, simde_wasm_v128_load16_lane, u16, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane3, simde_wasm_v128_load16_lane, u16, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane4, simde_wasm_v128_load16_lane, u16, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane5, simde_wasm_v128_load16_lane, u16, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane6, simde_wasm_v128_load16_lane, u16, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane7, simde_wasm_v128_load16_lane, u16, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane0, simde_wasm_v128_load32_lane, u32, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane1, simde_wasm_v128_load32_lane, u32, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane2, simde_wasm_v128_load32_lane, u32, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane3, simde_wasm_v128_load32_lane, u32, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load64_lane0, simde_wasm_v128_load64_lane, u64, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load64_lane1, simde_wasm_v128_load64_lane, u64, 1)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_STORE(v128_store, v128)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_STORE_LANE(v128_store8_lane0, simde_wasm_v128_store8_lane, u8, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane1, simde_wasm_v128_store8_lane, u8, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane2, simde_wasm_v128_store8_lane, u8, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane3, simde_wasm_v128_store8_lane, u8, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane4, simde_wasm_v128_store8_lane, u8, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane5, simde_wasm_v128_store8_lane, u8, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane6, simde_wasm_v128_store8_lane, u8, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane7, simde_wasm_v128_store8_lane, u8, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane8, simde_wasm_v128_store8_lane, u8, 8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane9, simde_wasm_v128_store8_lane, u8, 9)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane10, simde_wasm_v128_store8_lane, u8, 10)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane11, simde_wasm_v128_store8_lane, u8, 11)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane12, simde_wasm_v128_store8_lane, u8, 12)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane13, simde_wasm_v128_store8_lane, u8, 13)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane14, simde_wasm_v128_store8_lane, u8, 14)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane15, simde_wasm_v128_store8_lane, u8, 15)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane0, simde_wasm_v128_store16_lane, u16, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane1, simde_wasm_v128_store16_lane, u16, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane2, simde_wasm_v128_store16_lane, u16, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane3, simde_wasm_v128_store16_lane, u16, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane4, simde_wasm_v128_store16_lane, u16, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane5, simde_wasm_v128_store16_lane, u16, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane6, simde_wasm_v128_store16_lane, u16, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane7, simde_wasm_v128_store16_lane, u16, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane0, simde_wasm_v128_store32_lane, u32, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane1, simde_wasm_v128_store32_lane, u32, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane2, simde_wasm_v128_store32_lane, u32, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane3, simde_wasm_v128_store32_lane, u32, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store64_lane0, simde_wasm_v128_store64_lane, u64, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store64_lane1, simde_wasm_v128_store64_lane, u64, 1)
)w2c_template"
R"w2c_template(// clang-format on
)w2c_template"
;

Просмотреть файл

@ -271,235 +271,6 @@ R"w2c_template(DEFINE_STORE(i64_store16, u16, u64)
R"w2c_template(DEFINE_STORE(i64_store32, u32, u64) R"w2c_template(DEFINE_STORE(i64_store32, u32, u64)
)w2c_template" )w2c_template"
R"w2c_template( R"w2c_template(
#if defined(WASM_RT_ENABLE_SIMD)
)w2c_template"
R"w2c_template(
#ifdef __x86_64__
)w2c_template"
R"w2c_template(#define SIMD_FORCE_READ(var) wasm_asm("" ::"x"(var));
)w2c_template"
R"w2c_template(#else
)w2c_template"
R"w2c_template(#define SIMD_FORCE_READ(var)
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(// TODO: equivalent constraint for ARM and other architectures
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_LOAD_FUNC(name, func, t) \
)w2c_template"
R"w2c_template( static inline v128 name(wasm_rt_memory_t* mem, u64 addr) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( v128 result = func((v128*)&mem->data[addr]); \
)w2c_template"
R"w2c_template( SIMD_FORCE_READ(result); \
)w2c_template"
R"w2c_template( return result; \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_LOAD_LANE(name, func, t, lane) \
)w2c_template"
R"w2c_template( static inline v128 name(wasm_rt_memory_t* mem, u64 addr, v128 vec) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( v128 result = func((v128*)&mem->data[addr], vec, lane); \
)w2c_template"
R"w2c_template( SIMD_FORCE_READ(result); \
)w2c_template"
R"w2c_template( return result; \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_STORE(name, t) \
)w2c_template"
R"w2c_template( static inline void name(wasm_rt_memory_t* mem, u64 addr, v128 value) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( simde_wasm_v128_store((v128*)&mem->data[addr], value); \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
#define DEFINE_SIMD_STORE_LANE(name, func, t, lane) \
)w2c_template"
R"w2c_template( static inline void name(wasm_rt_memory_t* mem, u64 addr, v128 value) { \
)w2c_template"
R"w2c_template( MEMCHECK(mem, addr, t); \
)w2c_template"
R"w2c_template( func((v128*)&mem->data[addr], value, lane); \
)w2c_template"
R"w2c_template( }
)w2c_template"
R"w2c_template(
// clang-format off
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load, simde_wasm_v128_load, v128)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(v128_load8_splat, simde_wasm_v128_load8_splat, u8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load16_splat, simde_wasm_v128_load16_splat, u16)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load32_splat, simde_wasm_v128_load32_splat, u32)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load64_splat, simde_wasm_v128_load64_splat, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(i16x8_load8x8, simde_wasm_i16x8_load8x8, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u16x8_load8x8, simde_wasm_u16x8_load8x8, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(i32x4_load16x4, simde_wasm_i32x4_load16x4, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u32x4_load16x4, simde_wasm_u32x4_load16x4, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(i64x2_load32x2, simde_wasm_i64x2_load32x2, u64)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(u64x2_load32x2, simde_wasm_u64x2_load32x2, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_FUNC(v128_load32_zero, simde_wasm_v128_load32_zero, u32)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_FUNC(v128_load64_zero, simde_wasm_v128_load64_zero, u64)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_LOAD_LANE(v128_load8_lane0, simde_wasm_v128_load8_lane, u8, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane1, simde_wasm_v128_load8_lane, u8, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane2, simde_wasm_v128_load8_lane, u8, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane3, simde_wasm_v128_load8_lane, u8, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane4, simde_wasm_v128_load8_lane, u8, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane5, simde_wasm_v128_load8_lane, u8, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane6, simde_wasm_v128_load8_lane, u8, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane7, simde_wasm_v128_load8_lane, u8, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane8, simde_wasm_v128_load8_lane, u8, 8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane9, simde_wasm_v128_load8_lane, u8, 9)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane10, simde_wasm_v128_load8_lane, u8, 10)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane11, simde_wasm_v128_load8_lane, u8, 11)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane12, simde_wasm_v128_load8_lane, u8, 12)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane13, simde_wasm_v128_load8_lane, u8, 13)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane14, simde_wasm_v128_load8_lane, u8, 14)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load8_lane15, simde_wasm_v128_load8_lane, u8, 15)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane0, simde_wasm_v128_load16_lane, u16, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane1, simde_wasm_v128_load16_lane, u16, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane2, simde_wasm_v128_load16_lane, u16, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane3, simde_wasm_v128_load16_lane, u16, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane4, simde_wasm_v128_load16_lane, u16, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane5, simde_wasm_v128_load16_lane, u16, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane6, simde_wasm_v128_load16_lane, u16, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load16_lane7, simde_wasm_v128_load16_lane, u16, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane0, simde_wasm_v128_load32_lane, u32, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane1, simde_wasm_v128_load32_lane, u32, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane2, simde_wasm_v128_load32_lane, u32, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load32_lane3, simde_wasm_v128_load32_lane, u32, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load64_lane0, simde_wasm_v128_load64_lane, u64, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_LOAD_LANE(v128_load64_lane1, simde_wasm_v128_load64_lane, u64, 1)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_STORE(v128_store, v128)
)w2c_template"
R"w2c_template(
DEFINE_SIMD_STORE_LANE(v128_store8_lane0, simde_wasm_v128_store8_lane, u8, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane1, simde_wasm_v128_store8_lane, u8, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane2, simde_wasm_v128_store8_lane, u8, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane3, simde_wasm_v128_store8_lane, u8, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane4, simde_wasm_v128_store8_lane, u8, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane5, simde_wasm_v128_store8_lane, u8, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane6, simde_wasm_v128_store8_lane, u8, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane7, simde_wasm_v128_store8_lane, u8, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane8, simde_wasm_v128_store8_lane, u8, 8)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane9, simde_wasm_v128_store8_lane, u8, 9)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane10, simde_wasm_v128_store8_lane, u8, 10)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane11, simde_wasm_v128_store8_lane, u8, 11)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane12, simde_wasm_v128_store8_lane, u8, 12)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane13, simde_wasm_v128_store8_lane, u8, 13)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane14, simde_wasm_v128_store8_lane, u8, 14)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store8_lane15, simde_wasm_v128_store8_lane, u8, 15)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane0, simde_wasm_v128_store16_lane, u16, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane1, simde_wasm_v128_store16_lane, u16, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane2, simde_wasm_v128_store16_lane, u16, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane3, simde_wasm_v128_store16_lane, u16, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane4, simde_wasm_v128_store16_lane, u16, 4)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane5, simde_wasm_v128_store16_lane, u16, 5)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane6, simde_wasm_v128_store16_lane, u16, 6)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store16_lane7, simde_wasm_v128_store16_lane, u16, 7)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane0, simde_wasm_v128_store32_lane, u32, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane1, simde_wasm_v128_store32_lane, u32, 1)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane2, simde_wasm_v128_store32_lane, u32, 2)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store32_lane3, simde_wasm_v128_store32_lane, u32, 3)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store64_lane0, simde_wasm_v128_store64_lane, u64, 0)
)w2c_template"
R"w2c_template(DEFINE_SIMD_STORE_LANE(v128_store64_lane1, simde_wasm_v128_store64_lane, u64, 1)
)w2c_template"
R"w2c_template(// clang-format on
)w2c_template"
R"w2c_template(#endif
)w2c_template"
R"w2c_template(
#if defined(_MSC_VER) #if defined(_MSC_VER)
)w2c_template" )w2c_template"
R"w2c_template( R"w2c_template(

1
third_party/wasm2c/src/tools/wasm2c.cc поставляемый
Просмотреть файл

@ -100,7 +100,6 @@ static void ParseOptions(int argc, char** argv) {
ConvertBackslashToSlash(&s_infile); ConvertBackslashToSlash(&s_infile);
}); });
parser.Parse(argc, argv); parser.Parse(argc, argv);
s_write_c_options.features = &s_features;
bool any_non_supported_feature = false; bool any_non_supported_feature = false;
#define WABT_FEATURE(variable, flag, default_, help) \ #define WABT_FEATURE(variable, flag, default_, help) \