Refactoring bytecode_module to use flatcc instead of flatbuffers C++.
This improves our validation, removes manually-synchronized redundancy
with the schema for function descriptors, and optimizes a few things like
redundant type resolution.
diff --git a/build_tools/embed_data/generate_cc_embed_data.cc b/build_tools/embed_data/generate_cc_embed_data.cc
index 21275cc..9c0e290 100644
--- a/build_tools/embed_data/generate_cc_embed_data.cc
+++ b/build_tools/embed_data/generate_cc_embed_data.cc
@@ -110,14 +110,12 @@
const std::vector<std::string>& input_files,
const std::vector<std::string>& toc_files) {
std::ofstream f(impl_file, std::ios::out | std::ios::trunc);
+ f << "#include <cstdalign>\n";
f << "#include <cstddef>\n";
GenerateTocStruct(f);
GenerateNamespaceOpen(f);
- f << "static const struct ::iree::FileToc toc[] = {\n";
- assert(input_files.size() == toc_files.size());
for (size_t i = 0, e = input_files.size(); i < e; ++i) {
- f << " {";
- f << "\"" << absl::CEscape(toc_files[i]) << "\",\n";
+ f << "alignas(alignof(void*)) static char const file_" << i << "[] = {\n";
std::string contents;
if (!SlurpFile(input_files[i], &contents)) {
std::cerr << "Error reading file " << input_files[i] << "\n";
@@ -130,7 +128,16 @@
f << "\"" << absl::CHexEscape(line) << "\"\n";
remaining_contents = remaining_contents.substr(line.size());
}
- f << "\"\\0\", " << contents.size() << "},\n";
+ f << "};\n";
+ }
+ f << "static const struct ::iree::FileToc toc[] = {\n";
+ assert(input_files.size() == toc_files.size());
+ for (size_t i = 0, e = input_files.size(); i < e; ++i) {
+ f << " {\n";
+ f << " \"" << absl::CEscape(toc_files[i]) << "\",\n";
+ f << " file_" << i << ",\n";
+ f << " sizeof(file_" << i << ") - 1\n";
+ f << " },\n";
}
f << " {nullptr, nullptr, 0},\n";
f << "};\n";
diff --git a/iree/schemas/bytecode_module_def.fbs b/iree/schemas/bytecode_module_def.fbs
index 2eafefa..6eff279 100644
--- a/iree/schemas/bytecode_module_def.fbs
+++ b/iree/schemas/bytecode_module_def.fbs
@@ -117,6 +117,7 @@
// Offset and length within the larger bytecode data block.
bytecode_offset:int32;
bytecode_length:int32;
+ // TODO(benvanik): remove counts and embed directly in bytecode.
// Total number of i32 registers used by the function.
i32_register_count:int16;
// Total number of ref_ptr registers used by the function.
diff --git a/iree/vm/BUILD b/iree/vm/BUILD
index 370c47a..ceec083 100644
--- a/iree/vm/BUILD
+++ b/iree/vm/BUILD
@@ -59,13 +59,10 @@
":value",
"//iree/base:alignment",
"//iree/base:api",
- "//iree/base:flatbuffer_util",
+ "//iree/base:logging",
"//iree/base:target_platform",
"//iree/schemas:bytecode_module_def_c_fbs",
- "//iree/schemas:bytecode_module_def_cc_fbs",
"@com_github_dvidelabs_flatcc//:runtime",
- "@com_github_google_flatbuffers//:flatbuffers",
- "@com_google_absl//absl/strings",
],
)
diff --git a/iree/vm/CMakeLists.txt b/iree/vm/CMakeLists.txt
index b3c2442..84b8bf5 100644
--- a/iree/vm/CMakeLists.txt
+++ b/iree/vm/CMakeLists.txt
@@ -64,15 +64,12 @@
::stack
::type_def
::value
- absl::strings
- flatbuffers
flatcc::runtime
iree::base::alignment
iree::base::api
- iree::base::flatbuffer_util
+ iree::base::logging
iree::base::target_platform
iree::schemas::bytecode_module_def_c_fbs
- iree::schemas::bytecode_module_def_cc_fbs
PUBLIC
)
diff --git a/iree/vm/bytecode_dispatch.c b/iree/vm/bytecode_dispatch.c
index d313d17..86b5d1d 100644
--- a/iree/vm/bytecode_dispatch.c
+++ b/iree/vm/bytecode_dispatch.c
@@ -745,7 +745,7 @@
target_function.module = &module->interface;
target_function.linkage = IREE_VM_FUNCTION_LINKAGE_INTERNAL;
target_function.ordinal = function_ordinal;
- const iree_vm_function_descriptor_t* target_descriptor =
+ const iree_vm_FunctionDescriptor_t* target_descriptor =
&module->function_descriptor_table[function_ordinal];
target_function.i32_register_count =
target_descriptor->i32_register_count;
diff --git a/iree/vm/bytecode_module.cc b/iree/vm/bytecode_module.cc
index 560f102..cec96fd 100644
--- a/iree/vm/bytecode_module.cc
+++ b/iree/vm/bytecode_module.cc
@@ -14,28 +14,20 @@
#include "iree/vm/bytecode_module.h"
-#include <string.h>
-
-#include "absl/strings/match.h"
#include "iree/base/alignment.h"
#include "iree/base/api.h"
-#include "iree/base/flatbuffer_util.h"
+#include "iree/base/logging.h"
#include "iree/vm/bytecode_module_impl.h"
#include "iree/vm/ref.h"
#include "iree/vm/stack.h"
-// NOTE: include order matters:
-#include "flatcc/reflection/flatbuffers_common_reader.h"
-#include "iree/schemas/bytecode_module_def_reader.h"
-#include "iree/schemas/bytecode_module_def_verifier.h"
-
-// TODO(benvanik): replace with flatcc version so this file can be pure C.
-#include "flatbuffers/flatbuffers.h"
-#include "iree/schemas/bytecode_module_def_generated.h"
-
-#define IREE_VM_GET_MODULE_DEF(module) \
- ::flatbuffers::GetRoot<iree::vm::BytecodeModuleDef>( \
- module->flatbuffer_data.data)
+// Perform an strcmp between a flatbuffers string and an IREE string view.
+static bool iree_vm_flatbuffer_strcmp(flatbuffers_string_t lhs,
+ iree_string_view_t rhs) {
+ size_t lhs_size = flatbuffers_string_len(lhs);
+ int x = strncmp(lhs, rhs.data, lhs_size < rhs.size ? lhs_size : rhs.size);
+ return x != 0 ? x : lhs_size < rhs.size ? -1 : lhs_size > rhs.size;
+}
// Returns true if the given |type_def| is valid, meaning that the type it was
// resolved from is registered or known to the system as a builtin.
@@ -46,28 +38,36 @@
// Resolves a type through either builtin rules or the ref registered types.
static iree_vm_type_def_t iree_vm_bytecode_module_resolve_type(
- const iree::vm::TypeDef* type_def) {
- auto full_name = iree::WrapString(type_def->full_name());
+ iree_vm_TypeDef_table_t type_def) {
iree_vm_type_def_t result;
memset(&result, 0, sizeof(result));
- if (full_name == "i8") {
+ flatbuffers_string_t full_name = iree_vm_TypeDef_full_name(type_def);
+ if (!flatbuffers_string_len(full_name)) {
+ return result;
+ } else if (iree_vm_flatbuffer_strcmp(full_name,
+ iree_make_cstring_view("i8")) == 0) {
result.value_type = IREE_VM_VALUE_TYPE_I8;
- } else if (full_name == "i16") {
+ } else if (iree_vm_flatbuffer_strcmp(full_name,
+ iree_make_cstring_view("i16")) == 0) {
result.value_type = IREE_VM_VALUE_TYPE_I16;
- } else if (full_name == "i32") {
+ } else if (iree_vm_flatbuffer_strcmp(full_name,
+ iree_make_cstring_view("i32")) == 0) {
result.value_type = IREE_VM_VALUE_TYPE_I32;
- } else if (full_name == "i64") {
+ } else if (iree_vm_flatbuffer_strcmp(full_name,
+ iree_make_cstring_view("i64")) == 0) {
result.value_type = IREE_VM_VALUE_TYPE_I64;
- } else if (!full_name.empty() && full_name[0] == '!') {
- full_name.remove_prefix(1);
- if (absl::StartsWith(full_name, "vm.list<")) {
+ } else if (full_name[0] == '!') {
+ // Note that we drop the ! prefix:
+ iree_string_view_t type_name = iree_string_view_t{
+ full_name + 1, flatbuffers_string_len(full_name) - 1};
+ if (strncmp(type_name.data, "vm.list<", strlen("vm.list<")) == 0) {
// This is a !vm.list<...> type. We don't actually care about the type as
- // we allow list types to be widened.
- full_name.remove_suffix(full_name.size() - 7);
+ // we allow list types to be widened. Rewrite to just vm.list as that's
+ // all we have registered.
+ type_name = iree_make_cstring_view("vm.list");
}
const iree_vm_ref_type_descriptor_t* type_descriptor =
- iree_vm_ref_lookup_registered_type(
- iree_string_view_t{full_name.data(), full_name.size()});
+ iree_vm_ref_lookup_registered_type(type_name);
if (type_descriptor) {
result.ref_type = type_descriptor->type;
}
@@ -79,12 +79,13 @@
// |type_table| can be omitted to just perform verification that all types are
// registered.
static iree_status_t iree_vm_bytecode_module_resolve_types(
- const iree::vm::BytecodeModuleDef* module_def,
- iree_vm_type_def_t* type_table) {
- for (int i = 0; i < module_def->types()->size(); ++i) {
- type_table[i] =
- iree_vm_bytecode_module_resolve_type(module_def->types()->Get(i));
+ iree_vm_TypeDef_vec_t type_defs, iree_vm_type_def_t* type_table) {
+ for (size_t i = 0; i < iree_vm_TypeDef_vec_len(type_defs); ++i) {
+ iree_vm_TypeDef_table_t type_def = iree_vm_TypeDef_vec_at(type_defs, i);
+ type_table[i] = iree_vm_bytecode_module_resolve_type(type_def);
if (!iree_vm_type_def_is_valid(type_table[i])) {
+ LOG(ERROR) << "no type registered with name '"
+ << iree_vm_TypeDef_full_name(type_def) << "'";
return IREE_STATUS_NOT_FOUND;
}
}
@@ -96,121 +97,136 @@
// names on functions with internal linkage), however we shouldn't need to
// bounds check anything within the flatbuffer after this succeeds.
static iree_status_t iree_vm_bytecode_module_flatbuffer_verify(
- const iree::vm::BytecodeModuleDef* module_def) {
- if (!module_def->name() || module_def->name()->size() == 0) {
- LOG(ERROR) << "All modules must have a name.";
+ iree_const_byte_span_t flatbuffer_data) {
+ if (!flatbuffer_data.data || flatbuffer_data.data_length < 16) {
+ LOG(ERROR) << "Flatbuffer data is not present or less than 16 bytes";
return IREE_STATUS_INVALID_ARGUMENT;
}
- if (!module_def->types()) {
- LOG(ERROR) << "Type table is mandatory, though it could be empty (in empty "
- "modules).";
+ // Run flatcc generated verification. This ensures all pointers are in-bounds
+ // and that we can safely walk the file, but not that the actual contents of
+ // the flatbuffer meet our expectations.
+ int verify_ret = iree_vm_BytecodeModuleDef_verify_as_root(
+ flatbuffer_data.data, flatbuffer_data.data_length);
+ if (verify_ret != flatcc_verify_ok) {
+ LOG(ERROR) << flatcc_verify_error_string(verify_ret);
return IREE_STATUS_INVALID_ARGUMENT;
}
- if (!module_def->exported_functions() ||
- module_def->exported_functions()->size() == 0) {
- LOG(ERROR) << "At least one exported function is required.";
+ iree_vm_BytecodeModuleDef_table_t module_def =
+ iree_vm_BytecodeModuleDef_as_root(flatbuffer_data.data);
+
+ flatbuffers_string_t name = iree_vm_BytecodeModuleDef_name(module_def);
+ if (!flatbuffers_string_len(name)) {
+ LOG(ERROR) << "module name missing";
return IREE_STATUS_INVALID_ARGUMENT;
}
- if (!module_def->internal_functions() ||
- module_def->internal_functions()->size() == 0) {
- LOG(ERROR) << "At least one internal function is required.";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
-
- if (!module_def->function_descriptors() ||
- module_def->function_descriptors()->size() !=
- module_def->internal_functions()->size()) {
- LOG(ERROR)
- << "All internal functions need a mapping into the bytecode data.";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
-
- if (!module_def->bytecode_data()) {
- LOG(ERROR) << "Bytecode data is required if we have any functions.";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
-
- for (int i = 0; i < module_def->types()->size(); ++i) {
- const auto* type_def = module_def->types()->Get(i);
+ iree_vm_TypeDef_vec_t types = iree_vm_BytecodeModuleDef_types(module_def);
+ for (size_t i = 0; i < iree_vm_TypeDef_vec_len(types); ++i) {
+ iree_vm_TypeDef_table_t type_def = iree_vm_TypeDef_vec_at(types, i);
if (!type_def) {
- LOG(ERROR) << "All types must be valid.";
- return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!type_def->full_name() || type_def->full_name()->size() == 0) {
- LOG(ERROR) << "All types require a name.";
+ LOG(ERROR) << "type def missing body";
return IREE_STATUS_INVALID_ARGUMENT;
}
- if (!iree_vm_type_def_is_valid(
- iree_vm_bytecode_module_resolve_type(type_def))) {
- LOG(ERROR) << "No type registered with name '"
- << type_def->full_name()->c_str() << "'.";
+ flatbuffers_string_t full_name = iree_vm_TypeDef_full_name(type_def);
+ if (flatbuffers_string_len(full_name) <= 0) {
+ LOG(ERROR) << "type def missing full_name";
return IREE_STATUS_INVALID_ARGUMENT;
}
}
- if (module_def->imported_functions()) {
- for (int i = 0; i < module_def->imported_functions()->size(); ++i) {
- auto* import_def = module_def->imported_functions()->Get(i);
- if (!import_def) {
- LOG(ERROR) << "All imports must be valid.";
- return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!import_def->full_name() ||
- import_def->full_name()->size() == 0) {
- LOG(ERROR) << "All imports require a name.";
- return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!import_def->signature()) {
- LOG(ERROR) << "All imports require a signature.";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
+ iree_vm_ImportFunctionDef_vec_t imported_functions =
+ iree_vm_BytecodeModuleDef_imported_functions(module_def);
+ iree_vm_ExportFunctionDef_vec_t exported_functions =
+ iree_vm_BytecodeModuleDef_exported_functions(module_def);
+ iree_vm_InternalFunctionDef_vec_t internal_functions =
+ iree_vm_BytecodeModuleDef_internal_functions(module_def);
+ iree_vm_FunctionDescriptor_vec_t function_descriptors =
+ iree_vm_BytecodeModuleDef_function_descriptors(module_def);
+
+ if (flatbuffers_vec_len(internal_functions) !=
+ flatbuffers_vec_len(function_descriptors)) {
+ LOG(ERROR)
+ << "mismatched internal_functions and function_descriptors vectors";
+ return IREE_STATUS_INVALID_ARGUMENT;
+ }
+
+ for (size_t i = 0; i < iree_vm_ImportFunctionDef_vec_len(imported_functions);
+ ++i) {
+ iree_vm_ImportFunctionDef_table_t import_def =
+ iree_vm_ImportFunctionDef_vec_at(imported_functions, i);
+ if (!import_def) {
+ LOG(ERROR) << "import def missing body";
+ return IREE_STATUS_INVALID_ARGUMENT;
+ }
+ flatbuffers_string_t full_name =
+ iree_vm_ImportFunctionDef_full_name(import_def);
+ if (!flatbuffers_string_len(full_name)) {
+ LOG(ERROR) << "import def missing full_name";
+ return IREE_STATUS_INVALID_ARGUMENT;
+ }
+ if (!iree_vm_ImportFunctionDef_signature(import_def)) {
+ LOG(ERROR) << "import def missing a function signature";
+ return IREE_STATUS_INVALID_ARGUMENT;
}
}
- for (int i = 0; i < module_def->exported_functions()->size(); ++i) {
- auto* export_def = module_def->exported_functions()->Get(i);
+ for (size_t i = 0; i < iree_vm_ExportFunctionDef_vec_len(exported_functions);
+ ++i) {
+ iree_vm_ExportFunctionDef_table_t export_def =
+ iree_vm_ExportFunctionDef_vec_at(exported_functions, i);
if (!export_def) {
- LOG(ERROR) << "All exports must be valid.";
+ LOG(ERROR) << "export def missing body";
return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!export_def->local_name() ||
- export_def->local_name()->size() == 0) {
- LOG(ERROR) << "All exports require a name.";
+ }
+ flatbuffers_string_t local_name =
+ iree_vm_ExportFunctionDef_local_name(export_def);
+ if (!flatbuffers_string_len(local_name)) {
+ LOG(ERROR) << "export def missing local_name";
return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!export_def->signature()) {
- LOG(ERROR) << "All exports require a signature.";
+ }
+ if (!iree_vm_ExportFunctionDef_signature(export_def)) {
+ LOG(ERROR) << "export def missing a function signature";
return IREE_STATUS_INVALID_ARGUMENT;
- } else if (export_def->internal_ordinal() < 0 ||
- export_def->internal_ordinal() >=
- module_def->internal_functions()->size()) {
- LOG(ERROR)
- << "Out-of-bounds reference to a function in the internal table.";
+ }
+ int32_t internal_ordinal =
+ iree_vm_ExportFunctionDef_internal_ordinal(export_def);
+ if (internal_ordinal < 0 ||
+ internal_ordinal >=
+ iree_vm_InternalFunctionDef_vec_len(internal_functions)) {
+ LOG(ERROR) << "export def internal_ordinal out of bounds";
return IREE_STATUS_INVALID_ARGUMENT;
}
}
- for (int i = 0; i < module_def->internal_functions()->size(); ++i) {
- auto* function_def = module_def->internal_functions()->Get(i);
+ flatbuffers_uint8_vec_t bytecode_data =
+ iree_vm_BytecodeModuleDef_bytecode_data(module_def);
+ for (size_t i = 0;
+ i < iree_vm_InternalFunctionDef_vec_len(internal_functions); ++i) {
+ iree_vm_InternalFunctionDef_table_t function_def =
+ iree_vm_InternalFunctionDef_vec_at(internal_functions, i);
if (!function_def) {
- LOG(ERROR) << "All functions must be valid.";
+ LOG(ERROR) << "function def missing body";
return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!function_def->signature()) {
- LOG(ERROR) << "All functions require a signature.";
+ }
+ if (!iree_vm_InternalFunctionDef_signature(function_def)) {
+ LOG(ERROR) << "function def missing signature";
return IREE_STATUS_INVALID_ARGUMENT;
}
- const auto* function_descriptor =
- module_def->function_descriptors()->Get(i);
- if (!function_descriptor || function_descriptor->bytecode_offset() < 0 ||
- function_descriptor->bytecode_length() < 0 ||
- function_descriptor->bytecode_offset() +
- function_descriptor->bytecode_length() >
- module_def->bytecode_data()->size()) {
- LOG(ERROR) << "Bytecode span must be a valid range.";
+ iree_vm_FunctionDescriptor_struct_t function_descriptor =
+ iree_vm_FunctionDescriptor_vec_at(function_descriptors, i);
+ if (function_descriptor->bytecode_offset < 0 ||
+ function_descriptor->bytecode_offset +
+ function_descriptor->bytecode_length >
+ flatbuffers_uint8_vec_len(bytecode_data)) {
+ LOG(ERROR) << "function descriptor bytecode span out of range";
return IREE_STATUS_INVALID_ARGUMENT;
}
- if (function_descriptor->i32_register_count() > IREE_I32_REGISTER_COUNT ||
- function_descriptor->ref_register_count() > IREE_REF_REGISTER_COUNT) {
- LOG(ERROR) << "Register counts out of range.";
+ if (function_descriptor->i32_register_count > IREE_I32_REGISTER_COUNT ||
+ function_descriptor->ref_register_count > IREE_REF_REGISTER_COUNT) {
+ LOG(ERROR) << "function descriptor register out of range";
return IREE_STATUS_INVALID_ARGUMENT;
}
@@ -233,22 +249,21 @@
static iree_string_view_t iree_vm_bytecode_module_name(void* self) {
iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
- return iree_string_view_t{module_def->name()->data(),
- module_def->name()->size()};
+ flatbuffers_string_t name = iree_vm_BytecodeModuleDef_name(module->def);
+ return iree_string_view_t{name, flatbuffers_string_len(name)};
}
static iree_vm_module_signature_t iree_vm_bytecode_module_signature(
void* self) {
iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
iree_vm_module_signature_t signature;
- signature.import_function_count =
- module_def->imported_functions()
- ? module_def->imported_functions()->size()
- : 0;
- signature.export_function_count = module_def->exported_functions()->size();
- signature.internal_function_count = module_def->internal_functions()->size();
+ memset(&signature, 0, sizeof(signature));
+ signature.import_function_count = iree_vm_ImportFunctionDef_vec_len(
+ iree_vm_BytecodeModuleDef_imported_functions(module->def));
+ signature.export_function_count = iree_vm_ExportFunctionDef_vec_len(
+ iree_vm_BytecodeModuleDef_exported_functions(module->def));
+ signature.internal_function_count = iree_vm_InternalFunctionDef_vec_len(
+ iree_vm_BytecodeModuleDef_internal_functions(module->def));
return signature;
}
@@ -257,66 +272,75 @@
iree_vm_function_t* out_function, iree_string_view_t* out_name,
iree_vm_function_signature_t* out_signature) {
if (out_function) {
- memset(out_function, 0, sizeof(iree_vm_function_t));
+ memset(out_function, 0, sizeof(*out_function));
}
if (out_name) {
- out_name->data = NULL;
- out_name->size = 0;
+ memset(out_name, 0, sizeof(*out_name));
}
if (out_signature) {
- memset(out_signature, 0, sizeof(iree_vm_function_signature_t));
+ memset(out_signature, 0, sizeof(*out_signature));
}
iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
-
- const ::flatbuffers::String* name = nullptr;
- const iree::vm::FunctionSignatureDef* signature = nullptr;
+ flatbuffers_string_t name = NULL;
+ iree_vm_FunctionSignatureDef_table_t signature = NULL;
if (linkage == IREE_VM_FUNCTION_LINKAGE_IMPORT) {
- if (!module_def->imported_functions() || ordinal < 0 ||
- ordinal >= module_def->imported_functions()->size()) {
+ iree_vm_ImportFunctionDef_vec_t imported_functions =
+ iree_vm_BytecodeModuleDef_imported_functions(module->def);
+ if (ordinal < 0 ||
+ ordinal >= iree_vm_ImportFunctionDef_vec_len(imported_functions)) {
return IREE_STATUS_INVALID_ARGUMENT;
}
- auto* import_def = module_def->imported_functions()->Get(ordinal);
- name = import_def->full_name();
- signature = import_def->signature();
+ iree_vm_ImportFunctionDef_table_t import_def =
+ iree_vm_ImportFunctionDef_vec_at(imported_functions, ordinal);
+ name = iree_vm_ImportFunctionDef_full_name(import_def);
+ signature = iree_vm_ImportFunctionDef_signature(import_def);
if (out_function) {
out_function->module = &module->interface;
out_function->linkage = linkage;
out_function->ordinal = ordinal;
}
} else if (linkage == IREE_VM_FUNCTION_LINKAGE_EXPORT) {
- if (ordinal < 0 || ordinal >= module_def->exported_functions()->size()) {
+ iree_vm_ExportFunctionDef_vec_t exported_functions =
+ iree_vm_BytecodeModuleDef_exported_functions(module->def);
+ if (ordinal < 0 ||
+ ordinal >= iree_vm_ExportFunctionDef_vec_len(exported_functions)) {
return IREE_STATUS_INVALID_ARGUMENT;
}
- auto* export_def = module_def->exported_functions()->Get(ordinal);
- name = export_def->local_name();
- signature = export_def->signature();
+ iree_vm_ExportFunctionDef_table_t export_def =
+ iree_vm_ExportFunctionDef_vec_at(exported_functions, ordinal);
+ name = iree_vm_ExportFunctionDef_local_name(export_def);
+ signature = iree_vm_ExportFunctionDef_signature(export_def);
if (out_function) {
out_function->module = &module->interface;
out_function->linkage = IREE_VM_FUNCTION_LINKAGE_INTERNAL;
- out_function->ordinal = export_def->internal_ordinal();
+ out_function->ordinal =
+ iree_vm_ExportFunctionDef_internal_ordinal(export_def);
- const iree_vm_function_descriptor_t* function_descriptor =
- &module->function_descriptor_table[export_def->internal_ordinal()];
+ const iree_vm_FunctionDescriptor_t* function_descriptor =
+ &module->function_descriptor_table[out_function->ordinal];
out_function->i32_register_count =
function_descriptor->i32_register_count;
out_function->ref_register_count =
function_descriptor->ref_register_count;
}
} else {
- if (ordinal < 0 || ordinal >= module_def->internal_functions()->size()) {
+ iree_vm_InternalFunctionDef_vec_t internal_functions =
+ iree_vm_BytecodeModuleDef_internal_functions(module->def);
+ if (ordinal < 0 ||
+ ordinal >= iree_vm_InternalFunctionDef_vec_len(internal_functions)) {
return IREE_STATUS_INVALID_ARGUMENT;
}
- auto* function_def = module_def->internal_functions()->Get(ordinal);
- name = function_def->local_name();
- signature = function_def->signature();
+ iree_vm_InternalFunctionDef_table_t function_def =
+ iree_vm_InternalFunctionDef_vec_at(internal_functions, ordinal);
+ name = iree_vm_InternalFunctionDef_local_name(function_def);
+ signature = iree_vm_InternalFunctionDef_signature(function_def);
if (out_function) {
out_function->module = &module->interface;
out_function->linkage = IREE_VM_FUNCTION_LINKAGE_INTERNAL;
out_function->ordinal = ordinal;
- const iree_vm_function_descriptor_t* function_descriptor =
+ const iree_vm_FunctionDescriptor_t* function_descriptor =
&module->function_descriptor_table[ordinal];
out_function->i32_register_count =
function_descriptor->i32_register_count;
@@ -326,14 +350,14 @@
}
if (out_name && name) {
- out_name->data = name->c_str();
- out_name->size = name->size();
+ out_name->data = name;
+ out_name->size = flatbuffers_string_len(name);
}
if (out_signature && signature) {
- out_signature->argument_count =
- signature->argument_types() ? signature->argument_types()->size() : 0;
- out_signature->result_count =
- signature->result_types() ? signature->result_types()->size() : 0;
+ out_signature->argument_count = flatbuffers_int32_vec_len(
+ iree_vm_FunctionSignatureDef_argument_types(signature));
+ out_signature->result_count = flatbuffers_int32_vec_len(
+ iree_vm_FunctionSignatureDef_result_types(signature));
}
return IREE_STATUS_OK;
@@ -342,9 +366,6 @@
static iree_status_t iree_vm_bytecode_module_get_function_reflection_attr(
void* self, iree_vm_function_linkage_t linkage, int32_t ordinal,
int32_t index, iree_string_view_t* key, iree_string_view_t* value) {
- iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
-
if (linkage != IREE_VM_FUNCTION_LINKAGE_INTERNAL) {
iree_vm_function_t internal_function;
iree_vm_bytecode_module_get_function(self, linkage, ordinal,
@@ -353,83 +374,98 @@
ordinal = internal_function.ordinal;
}
- if (ordinal < 0 || ordinal >= module_def->internal_functions()->size()) {
+ iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
+ iree_vm_InternalFunctionDef_vec_t internal_functions =
+ iree_vm_BytecodeModuleDef_internal_functions(module->def);
+
+ if (ordinal < 0 ||
+ ordinal >= iree_vm_InternalFunctionDef_vec_len(internal_functions)) {
return IREE_STATUS_INVALID_ARGUMENT;
}
- auto* export_def = module_def->internal_functions()->Get(ordinal);
- const iree::vm::FunctionSignatureDef* signature = export_def->signature();
- if (!signature->reflection_attrs() || index < 0 ||
- index >= signature->reflection_attrs()->size()) {
+ iree_vm_InternalFunctionDef_table_t function_def =
+ iree_vm_InternalFunctionDef_vec_at(internal_functions, ordinal);
+ iree_vm_FunctionSignatureDef_table_t signature =
+ iree_vm_InternalFunctionDef_signature(function_def);
+ iree_vm_ReflectionAttrDef_vec_t reflection_attrs =
+ iree_vm_FunctionSignatureDef_reflection_attrs(signature);
+ if (index < 0 ||
+ index >= iree_vm_ReflectionAttrDef_vec_len(reflection_attrs)) {
return IREE_STATUS_NOT_FOUND;
}
- const ::iree::vm::ReflectionAttrDef* attr =
- signature->reflection_attrs()->Get(index);
- const ::flatbuffers::String* attr_key = attr->key();
- const ::flatbuffers::String* attr_value = attr->value();
- if (!attr_key || !attr_value) {
+ iree_vm_ReflectionAttrDef_table_t attr =
+ iree_vm_ReflectionAttrDef_vec_at(reflection_attrs, index);
+ flatbuffers_string_t attr_key = iree_vm_ReflectionAttrDef_key(attr);
+ flatbuffers_string_t attr_value = iree_vm_ReflectionAttrDef_value(attr);
+ if (!flatbuffers_string_len(attr_key) ||
+ !flatbuffers_string_len(attr_value)) {
// Because reflection metadata should not impose any overhead for the
// non reflection case, we do not eagerly validate in on load -- instead
// verify it structurally as needed.
return IREE_STATUS_FAILED_PRECONDITION;
}
- key->data = attr_key->c_str();
- key->size = attr_key->size();
- value->data = attr_value->c_str();
- value->size = attr_value->size();
+ key->data = attr_key;
+ key->size = flatbuffers_string_len(attr_key);
+ value->data = attr_value;
+ value->size = flatbuffers_string_len(attr_value);
return IREE_STATUS_OK;
}
-static bool iree_vm_bytecode_module_compare_str(const flatbuffers::String* lhs,
- iree_string_view_t rhs) {
- if (!lhs || lhs->size() != rhs.size) return false;
- return strncmp(lhs->c_str(), rhs.data, rhs.size) == 0;
-}
-
static iree_status_t iree_vm_bytecode_module_lookup_function(
void* self, iree_vm_function_linkage_t linkage, iree_string_view_t name,
iree_vm_function_t* out_function) {
if (!out_function) return IREE_STATUS_INVALID_ARGUMENT;
memset(out_function, 0, sizeof(iree_vm_function_t));
- if (!name.data || !name.size) return IREE_STATUS_INVALID_ARGUMENT;
-
- iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
+ if (iree_string_view_is_empty(name)) return IREE_STATUS_INVALID_ARGUMENT;
// NOTE: we could organize imports/exports alphabetically so we could bsearch.
+ iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
if (linkage == IREE_VM_FUNCTION_LINKAGE_IMPORT) {
- if (!module_def->imported_functions()) {
- return IREE_STATUS_NOT_FOUND;
- }
- for (int ordinal = 0; ordinal < module_def->imported_functions()->size();
+ iree_vm_ImportFunctionDef_vec_t imported_functions =
+ iree_vm_BytecodeModuleDef_imported_functions(module->def);
+ for (size_t ordinal = 0;
+ ordinal < iree_vm_ImportFunctionDef_vec_len(imported_functions);
++ordinal) {
- auto* import_def = module_def->imported_functions()->Get(ordinal);
- if (iree_vm_bytecode_module_compare_str(import_def->full_name(), name)) {
+ iree_vm_ImportFunctionDef_table_t import_def =
+ iree_vm_ImportFunctionDef_vec_at(imported_functions, ordinal);
+ if (iree_vm_flatbuffer_strcmp(
+ iree_vm_ImportFunctionDef_full_name(import_def), name) == 0) {
return iree_vm_bytecode_module_get_function(self, linkage, ordinal,
out_function, NULL, NULL);
}
}
return IREE_STATUS_NOT_FOUND;
} else if (linkage == IREE_VM_FUNCTION_LINKAGE_EXPORT) {
- for (int ordinal = 0; ordinal < module_def->exported_functions()->size();
+ iree_vm_ExportFunctionDef_vec_t exported_functions =
+ iree_vm_BytecodeModuleDef_exported_functions(module->def);
+ for (size_t ordinal = 0;
+ ordinal < iree_vm_InternalFunctionDef_vec_len(exported_functions);
++ordinal) {
- auto* export_def = module_def->exported_functions()->Get(ordinal);
- if (iree_vm_bytecode_module_compare_str(export_def->local_name(), name)) {
+ iree_vm_ExportFunctionDef_table_t export_def =
+ iree_vm_ExportFunctionDef_vec_at(exported_functions, ordinal);
+ if (iree_vm_flatbuffer_strcmp(
+ iree_vm_ExportFunctionDef_local_name(export_def), name) == 0) {
return iree_vm_bytecode_module_get_function(
self, IREE_VM_FUNCTION_LINKAGE_INTERNAL,
- export_def->internal_ordinal(), out_function, NULL, NULL);
+ iree_vm_ExportFunctionDef_internal_ordinal(export_def),
+ out_function, NULL, NULL);
}
}
return IREE_STATUS_NOT_FOUND;
} else {
- for (int ordinal = 0; ordinal < module_def->internal_functions()->size();
+ iree_vm_InternalFunctionDef_vec_t internal_functions =
+ iree_vm_BytecodeModuleDef_internal_functions(module->def);
+ for (size_t ordinal = 0;
+ ordinal < iree_vm_InternalFunctionDef_vec_len(internal_functions);
++ordinal) {
- auto* function_def = module_def->internal_functions()->Get(ordinal);
- if (iree_vm_bytecode_module_compare_str(function_def->local_name(),
- name)) {
+ iree_vm_InternalFunctionDef_table_t function_def =
+ iree_vm_InternalFunctionDef_vec_at(internal_functions, ordinal);
+ if (iree_vm_flatbuffer_strcmp(
+ iree_vm_InternalFunctionDef_local_name(function_def), name) ==
+ 0) {
return iree_vm_bytecode_module_get_function(
self, IREE_VM_FUNCTION_LINKAGE_INTERNAL, ordinal, out_function,
NULL, NULL);
@@ -443,20 +479,21 @@
// Returns the total size of the structure and all tables with padding applied.
// |state| may be null if only the structure size is required for allocation.
static iree_host_size_t iree_vm_bytecode_module_layout_state(
- const iree::vm::BytecodeModuleDef* module_def,
+ iree_vm_BytecodeModuleDef_table_t module_def,
iree_vm_bytecode_module_state_t* state) {
- int rwdata_storage_capacity =
- module_def->module_state()
- ? module_def->module_state()->global_bytes_capacity()
- : 0;
- int global_ref_count = module_def->module_state()
- ? module_def->module_state()->global_ref_count()
- : 0;
- int rodata_ref_count =
- module_def->rodata_segments() ? module_def->rodata_segments()->size() : 0;
- int import_function_count = module_def->imported_functions()
- ? module_def->imported_functions()->size()
- : 0;
+ iree_vm_ModuleStateDef_table_t module_state =
+ iree_vm_BytecodeModuleDef_module_state(module_def);
+ int rwdata_storage_capacity = 0;
+ int global_ref_count = 0;
+ if (module_state) {
+ rwdata_storage_capacity =
+ iree_vm_ModuleStateDef_global_bytes_capacity(module_state);
+ global_ref_count = iree_vm_ModuleStateDef_global_ref_count(module_state);
+ }
+ int rodata_ref_count = iree_vm_RodataSegmentDef_vec_len(
+ iree_vm_BytecodeModuleDef_rodata_segments(module_def));
+ int import_function_count = iree_vm_ImportFunctionDef_vec_len(
+ iree_vm_BytecodeModuleDef_imported_functions(module_def));
uint8_t* base_ptr = (uint8_t*)state;
iree_host_size_t offset =
@@ -496,7 +533,7 @@
*out_module_state = NULL;
iree_vm_bytecode_module_t* module = (iree_vm_bytecode_module_t*)self;
- auto* module_def = IREE_VM_GET_MODULE_DEF(module);
+ iree_vm_BytecodeModuleDef_table_t module_def = module->def;
// Compute the total size required (with padding) for the state structure.
iree_host_size_t total_state_struct_size =
@@ -512,13 +549,16 @@
iree_vm_bytecode_module_layout_state(module_def, state);
// Setup rodata segments to point directly at the flatbuffer memory.
+ iree_vm_RodataSegmentDef_vec_t rodata_segments =
+ iree_vm_BytecodeModuleDef_rodata_segments(module_def);
for (int i = 0; i < state->rodata_ref_count; ++i) {
- const iree::vm::RodataSegmentDef* segment =
- module_def->rodata_segments()->Get(i);
+ iree_vm_RodataSegmentDef_table_t segment =
+ iree_vm_RodataSegmentDef_vec_at(rodata_segments, i);
iree_vm_ro_byte_buffer_t* ref = &state->rodata_ref_table[i];
iree_atomic_store(&ref->ref_object.counter, 1);
- ref->data.data = segment->data()->Data();
- ref->data.data_length = segment->data()->size();
+ ref->data.data = iree_vm_RodataSegmentDef_data(segment);
+ ref->data.data_length =
+ flatbuffers_uint8_vec_len(iree_vm_RodataSegmentDef_data(segment));
}
*out_module_state = (iree_vm_module_state_t*)state;
@@ -599,31 +639,24 @@
iree_const_byte_span_t flatbuffer_data,
iree_allocator_t flatbuffer_allocator, iree_allocator_t allocator,
iree_vm_module_t** out_module) {
- if (!out_module) {
- LOG(ERROR) << "Output module argument not set";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
+ if (!out_module) return IREE_STATUS_INVALID_ARGUMENT;
*out_module = NULL;
- if (!flatbuffer_data.data || flatbuffer_data.data_length < 16) {
- LOG(ERROR) << "Flatbuffer data is not present or less than 16 bytes";
- return IREE_STATUS_INVALID_ARGUMENT;
- } else if (!iree::vm::BytecodeModuleDefBufferHasIdentifier(
- flatbuffer_data.data)) {
- LOG(ERROR) << "Flatbuffer data does not have bytecode module identifier";
- return IREE_STATUS_INVALID_ARGUMENT;
- }
+ IREE_RETURN_IF_ERROR(
+ iree_vm_bytecode_module_flatbuffer_verify(flatbuffer_data));
- const iree::vm::BytecodeModuleDef* module_def =
- ::flatbuffers::GetRoot<iree::vm::BytecodeModuleDef>(flatbuffer_data.data);
+ iree_vm_BytecodeModuleDef_table_t module_def =
+ iree_vm_BytecodeModuleDef_as_root(flatbuffer_data.data);
if (!module_def) {
- LOG(ERROR) << "Failed getting root from flatbuffer data";
+ LOG(ERROR) << "failed getting root from flatbuffer data; expected "
+ "identifier " iree_vm_BytecodeModuleDef_file_identifier
+ " not found";
return IREE_STATUS_INVALID_ARGUMENT;
}
- IREE_RETURN_IF_ERROR(iree_vm_bytecode_module_flatbuffer_verify(module_def));
+ iree_vm_TypeDef_vec_t type_defs = iree_vm_BytecodeModuleDef_types(module_def);
size_t type_table_size =
- module_def->types()->size() * sizeof(iree_vm_type_def_t);
+ iree_vm_TypeDef_vec_len(type_defs) * sizeof(iree_vm_type_def_t);
iree_vm_bytecode_module_t* module = NULL;
IREE_RETURN_IF_ERROR(iree_allocator_malloc(
@@ -631,21 +664,30 @@
(void**)&module));
module->allocator = allocator;
+ iree_vm_FunctionDescriptor_vec_t function_descriptors =
+ iree_vm_BytecodeModuleDef_function_descriptors(module_def);
module->function_descriptor_count =
- module_def->function_descriptors()->size();
- module->function_descriptor_table =
- (const iree_vm_function_descriptor_t*)module_def->function_descriptors()
- ->data();
+ iree_vm_FunctionDescriptor_vec_len(function_descriptors);
+ module->function_descriptor_table = function_descriptors;
+
+ flatbuffers_uint8_vec_t bytecode_data =
+ iree_vm_BytecodeModuleDef_bytecode_data(module_def);
module->bytecode_data = iree_const_byte_span_t{
- module_def->bytecode_data()->Data(), module_def->bytecode_data()->size()};
+ bytecode_data, flatbuffers_uint8_vec_len(bytecode_data)};
module->flatbuffer_data = flatbuffer_data;
module->flatbuffer_allocator = flatbuffer_allocator;
+ module->def = module_def;
- module->type_count = module_def->types()->size();
+ module->type_count = iree_vm_TypeDef_vec_len(type_defs);
module->type_table = (iree_vm_type_def_t*)((uint8_t*)module +
sizeof(iree_vm_bytecode_module_t));
- iree_vm_bytecode_module_resolve_types(module_def, module->type_table);
+ iree_status_t resolve_status =
+ iree_vm_bytecode_module_resolve_types(type_defs, module->type_table);
+ if (!iree_status_is_ok(resolve_status)) {
+ iree_allocator_free(allocator, module);
+ return resolve_status;
+ }
iree_vm_module_initialize(&module->interface, module);
module->interface.destroy = iree_vm_bytecode_module_destroy;
diff --git a/iree/vm/bytecode_module_impl.h b/iree/vm/bytecode_module_impl.h
index da53486..bda8961 100644
--- a/iree/vm/bytecode_module_impl.h
+++ b/iree/vm/bytecode_module_impl.h
@@ -16,6 +16,13 @@
#define IREE_VM_BYTECODE_MODULE_IMPL_H_
#include <stdint.h>
+#include <string.h>
+
+// TODO(benvanik): figure out how to make MSVC happy with C11 stdalign.h.
+// #include <stdalign.h>
+#ifdef __cplusplus
+#include <cstdalign>
+#endif // __cplusplus
#include "iree/base/api.h"
#include "iree/vm/builtin_types.h"
@@ -25,18 +32,15 @@
#include "iree/vm/type_def.h"
#include "iree/vm/value.h"
+// NOTE: include order matters:
+#include "flatcc/reflection/flatbuffers_common_reader.h"
+#include "iree/schemas/bytecode_module_def_reader.h"
+#include "iree/schemas/bytecode_module_def_verifier.h"
+
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
-// Matches the FunctionDescriptor struct in the flatbuffer.
-typedef struct {
- int32_t bytecode_offset;
- int32_t bytecode_length;
- uint16_t i32_register_count;
- uint16_t ref_register_count;
-} iree_vm_function_descriptor_t;
-
// A loaded bytecode module.
typedef struct {
// Interface routing to the bytecode module functions.
@@ -48,7 +52,8 @@
// Mapped 1:1 with internal functions. Each defined bytecode span represents a
// range of bytes in |bytecode_data|.
int32_t function_descriptor_count;
- const iree_vm_function_descriptor_t* function_descriptor_table;
+ const iree_vm_FunctionDescriptor_t* function_descriptor_table;
+
// A pointer to the bytecode data embedded within the module.
iree_const_byte_span_t bytecode_data;
@@ -58,6 +63,7 @@
// Underlying FlatBuffer data and allocator (which may be null).
iree_const_byte_span_t flatbuffer_data;
iree_allocator_t flatbuffer_allocator;
+ iree_vm_BytecodeModuleDef_table_t def;
// Type table mapping module type IDs to registered VM types.
int32_t type_count;