Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa9572d33a | |||
| 8c0a31e19b | |||
| a20306ae64 | |||
| 99380c7810 | |||
| 2d396ee071 | |||
| 34a8ccff95 | |||
| d9835cea0b |
+3
-1
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(fx C ASM)
|
project(fx C ASM)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
include (TestBigEndian)
|
include (TestBigEndian)
|
||||||
include(Templates)
|
include(Templates)
|
||||||
include(Platform)
|
include(Platform)
|
||||||
@@ -59,4 +59,6 @@ foreach (assembly ${fx_assemblies})
|
|||||||
add_subdirectory(assemblies/${assembly})
|
add_subdirectory(assemblies/${assembly})
|
||||||
endforeach (assembly)
|
endforeach (assembly)
|
||||||
|
|
||||||
|
if (fx_enable_tests)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
endif ()
|
||||||
|
|||||||
+43
-108
@@ -49,43 +49,37 @@ if (FX_STATIC)
|
|||||||
set(_lib_suffix "-s")
|
set(_lib_suffix "-s")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(supported_components Core Ds Term Cmd Io Serial Compress)
|
set(assemblies ${FX_FIND_COMPONENTS})
|
||||||
set(components ${FX_FIND_COMPONENTS})
|
|
||||||
string(REPLACE ";" ", " supported_components_string_list "${supported_components}")
|
|
||||||
|
|
||||||
if (NOT components)
|
|
||||||
set(components ${supported_components})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(required_vars)
|
set(required_vars)
|
||||||
|
|
||||||
foreach (component ${components})
|
if (NOT FX_INCLUDE_DIR)
|
||||||
if (NOT "${component}" IN_LIST supported_components)
|
find_path(FX_INCLUDE_DIR
|
||||||
message(FATAL_ERROR "'${component}' is not a valid FX module.\nSupported modules: ${supported_components_string_list}")
|
NAMES fx/misc.h ${FX_FIND_ARGS}
|
||||||
endif ()
|
|
||||||
|
|
||||||
string(TOLOWER ${component} header_name)
|
|
||||||
set(lib_name ${header_name}${_lib_suffix})
|
|
||||||
|
|
||||||
if (NOT FX_${component}_INCLUDE_DIR)
|
|
||||||
find_path(FX_${component}_INCLUDE_DIR
|
|
||||||
NAMES fx/${header_name}.h ${FX_FIND_ARGS}
|
|
||||||
PATH_SUFFIXES include
|
PATH_SUFFIXES include
|
||||||
PATHS ${FX_SEARCH_PATHS})
|
PATHS ${FX_SEARCH_PATHS})
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT FX_${component}_LIBRARY)
|
set(required_vars FX_INCLUDE_DIR)
|
||||||
find_library(FX_${component}_LIBRARY
|
|
||||||
NAMES fx-${lib_name} ${FX_FIND_ARGS}
|
foreach (assembly ${assemblies})
|
||||||
|
string(TOLOWER ${assembly} header_name)
|
||||||
|
string(REPLACE "." "_" macro_name ${assembly})
|
||||||
|
string(TOUPPER ${macro_name} macro_name)
|
||||||
|
|
||||||
|
set(lib_name ${assembly}${_lib_suffix})
|
||||||
|
|
||||||
|
if (NOT ${macro_name}_LIBRARY)
|
||||||
|
find_library(${macro_name}_LIBRARY
|
||||||
|
NAMES ${lib_name} ${FX_FIND_ARGS}
|
||||||
PATH_SUFFIXES lib
|
PATH_SUFFIXES lib
|
||||||
PATHS ${FX_SEARCH_PATHS})
|
PATHS ${FX_SEARCH_PATHS})
|
||||||
else ()
|
else ()
|
||||||
# on Windows, ensure paths are in canonical format (forward slahes):
|
# on Windows, ensure paths are in canonical format (forward slahes):
|
||||||
file(TO_CMAKE_PATH "${FX_${component}_LIBRARY}" FX_${component}_LIBRARY)
|
file(TO_CMAKE_PATH "${${macro_name}_LIBRARY}" ${macro_name}_LIBRARY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND required_vars FX_${component}_INCLUDE_DIR FX_${component}_LIBRARY)
|
list(APPEND required_vars ${macro_name}_LIBRARY)
|
||||||
endforeach (component)
|
endforeach (assembly)
|
||||||
|
|
||||||
unset(FX_FIND_ARGS)
|
unset(FX_FIND_ARGS)
|
||||||
|
|
||||||
@@ -96,94 +90,35 @@ find_package_handle_standard_args(FX
|
|||||||
|
|
||||||
if (FX_FOUND)
|
if (FX_FOUND)
|
||||||
set(created_targets)
|
set(created_targets)
|
||||||
foreach (component ${components})
|
foreach (assembly ${assemblies})
|
||||||
string(TOLOWER ${component} header_name)
|
set(target_name ${assembly})
|
||||||
set(lib_name ${header_name}${_lib_suffix})
|
string(REPLACE "fx." "" target_name ${target_name})
|
||||||
|
string(SUBSTRING ${target_name} 0 1 target_name_prefix)
|
||||||
|
string(TOUPPER ${target_name_prefix} target_name_prefix)
|
||||||
|
string(SUBSTRING ${target_name} 1 -1 target_name_suffix)
|
||||||
|
set(target_name ${target_name_prefix}${target_name_suffix})
|
||||||
|
|
||||||
if(NOT TARGET FX::${component})
|
string(TOLOWER ${assembly} header_name)
|
||||||
add_library(FX::${component} UNKNOWN IMPORTED)
|
string(REPLACE "." "_" macro_name ${assembly})
|
||||||
set_target_properties(FX::${component} PROPERTIES
|
string(REPLACE "." "_" macro_name ${assembly})
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${FX_${component}_INCLUDE_DIR}")
|
string(TOUPPER ${macro_name} macro_name)
|
||||||
target_compile_definitions(FX::${component} INTERFACE _CRT_SECURE_NO_WARNINGS=1)
|
|
||||||
|
set(lib_name ${assembly}${_lib_suffix})
|
||||||
|
|
||||||
|
if (NOT TARGET FX::${target_name})
|
||||||
|
add_library(FX::${target_name} UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(FX::${target_name} PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${FX_INCLUDE_DIR}")
|
||||||
|
target_compile_definitions(FX::${target_name} INTERFACE _CRT_SECURE_NO_WARNINGS=1)
|
||||||
|
|
||||||
if (FX_STATIC)
|
if (FX_STATIC)
|
||||||
target_compile_definitions(FX::${component} INTERFACE FX_STATIC=1)
|
target_compile_definitions(FX::${target_name} INTERFACE FX_STATIC=1)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set_target_properties(FX::${component} PROPERTIES
|
set_target_properties(FX::${target_name} PROPERTIES
|
||||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||||
IMPORTED_LOCATION "${FX_${component}_LIBRARY}")
|
IMPORTED_LOCATION "${${macro_name}_LIBRARY}")
|
||||||
set(created_targets ${created_targets} ${component})
|
set(created_targets ${created_targets} ${assembly})
|
||||||
endif ()
|
endif ()
|
||||||
endforeach (component)
|
endforeach (assembly)
|
||||||
|
|
||||||
foreach (component ${created_targets})
|
|
||||||
if ("${component}" STREQUAL "Ds")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Ds' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Ds INTERFACE FX::Core)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ("${component}" STREQUAL "Term")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Term' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET FX::Ds)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Term' depends on 'Ds', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Term INTERFACE FX::Core FX::Ds)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ("${component}" STREQUAL "Serial")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Serial' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET FX::Ds)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Serial' depends on 'Ds', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Serial INTERFACE FX::Core FX::Ds)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ("${component}" STREQUAL "Cmd")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET FX::Ds)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Ds', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET FX::Term)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Cmd' depends on 'Term', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Cmd INTERFACE FX::Core FX::Ds FX::Term)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ("${component}" STREQUAL "Io")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Io' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET FX::Ds)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Io' depends on 'Ds', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Io INTERFACE FX::Core FX::Ds)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if ("${component}" STREQUAL "Compress")
|
|
||||||
if (NOT TARGET FX::Core)
|
|
||||||
message(FATAL_ERROR "FX: Module 'Compress' depends on 'Core', which was not specified in find_package()")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(FX::Compress INTERFACE FX::Core FX::Ds)
|
|
||||||
endif ()
|
|
||||||
endforeach (component)
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ function(get_platform_details)
|
|||||||
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||||
set(system_name "win32")
|
set(system_name "win32")
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
|
string(TOLOWER "${CMAKE_SYSTEM_NAME}" system_name)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
|
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
|
||||||
@@ -27,7 +27,7 @@ function(get_platform_details)
|
|||||||
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64")
|
elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64")
|
||||||
set(system_arch "aarch64")
|
set(system_arch "aarch64")
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" system_arch)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set(${arg_SYSTEM} ${system_name} PARENT_SCOPE)
|
set(${arg_SYSTEM} ${system_name} PARENT_SCOPE)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ function(add_fx_assembly)
|
|||||||
target_compile_definitions(${assembly_target_name} PRIVATE ${def})
|
target_compile_definitions(${assembly_target_name} PRIVATE ${def})
|
||||||
endforeach (def)
|
endforeach (def)
|
||||||
|
|
||||||
|
if (fx_enable_tests)
|
||||||
foreach (ns ${arg_NAMESPACES})
|
foreach (ns ${arg_NAMESPACES})
|
||||||
file(GLOB test_sources ${fx_source_root}/${ns}/test/*.c)
|
file(GLOB test_sources ${fx_source_root}/${ns}/test/*.c)
|
||||||
foreach (test_file ${test_sources})
|
foreach (test_file ${test_sources})
|
||||||
@@ -57,6 +58,7 @@ function(add_fx_assembly)
|
|||||||
target_link_libraries(${test_name} ${assembly_target_name})
|
target_link_libraries(${test_name} ${assembly_target_name})
|
||||||
endforeach (test_file)
|
endforeach (test_file)
|
||||||
endforeach (ns)
|
endforeach (ns)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set_target_properties(${assembly_target_name} PROPERTIES
|
set_target_properties(${assembly_target_name} PROPERTIES
|
||||||
FOLDER "${assembly_name}")
|
FOLDER "${assembly_name}")
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ struct fx_directory_iterator_p {
|
|||||||
fx_directory *root;
|
fx_directory *root;
|
||||||
|
|
||||||
fx_directory_entry entry;
|
fx_directory_entry entry;
|
||||||
|
fx_value entry_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
@@ -510,6 +511,8 @@ static void update_iterator_data(struct fx_directory_iterator_p *it)
|
|||||||
fx_path *path = fx_path_create_from_cstr(
|
fx_path *path = fx_path_create_from_cstr(
|
||||||
ent->fts_path + fx_path_length(it->_p->d_path_abs) + 1);
|
ent->fts_path + fx_path_length(it->_p->d_path_abs) + 1);
|
||||||
|
|
||||||
|
fx_value_unset(&it->entry_value);
|
||||||
|
it->entry_value = FX_POINTER(&it->entry);
|
||||||
it->entry.filename = ent->fts_name;
|
it->entry.filename = ent->fts_name;
|
||||||
it->entry.filepath = path;
|
it->entry.filepath = path;
|
||||||
|
|
||||||
@@ -616,12 +619,7 @@ fx_iterator *fx_directory_begin(
|
|||||||
return it_obj;
|
return it_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fx_iterator *iterator_begin(fx_object *obj)
|
static const fx_iterator *iterator_begin(const fx_object *obj)
|
||||||
{
|
|
||||||
return fx_directory_begin(obj, FX_DIRECTORY_ITERATE_PARENT_FIRST);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const fx_iterator *iterator_cbegin(const fx_object *obj)
|
|
||||||
{
|
{
|
||||||
return fx_directory_begin(
|
return fx_directory_begin(
|
||||||
(fx_object *)obj,
|
(fx_object *)obj,
|
||||||
@@ -692,20 +690,12 @@ static enum fx_status iterator_erase(fx_iterator *obj)
|
|||||||
return iterator_move_next(obj);
|
return iterator_move_next(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fx_iterator_value iterator_get_value(fx_iterator *obj)
|
static const fx_value *iterator_get_value(const fx_iterator *obj)
|
||||||
{
|
{
|
||||||
struct fx_directory_iterator_p *it
|
struct fx_directory_iterator_p *it
|
||||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
||||||
|
|
||||||
return FX_ITERATOR_VALUE_PTR(&it->entry);
|
return &it->entry_value;
|
||||||
}
|
|
||||||
|
|
||||||
static const fx_iterator_value iterator_get_cvalue(const fx_iterator *obj)
|
|
||||||
{
|
|
||||||
struct fx_directory_iterator_p *it
|
|
||||||
= fx_object_get_private(obj, FX_TYPE_DIRECTORY_ITERATOR);
|
|
||||||
|
|
||||||
return FX_ITERATOR_VALUE_CPTR(&it->entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** CLASS DEFINITION *********************************************************/
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
@@ -718,7 +708,6 @@ FX_TYPE_CLASS_BEGIN(fx_directory)
|
|||||||
|
|
||||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterable, FX_TYPE_ITERABLE)
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterable, FX_TYPE_ITERABLE)
|
||||||
FX_INTERFACE_ENTRY(it_begin) = iterator_begin;
|
FX_INTERFACE_ENTRY(it_begin) = iterator_begin;
|
||||||
FX_INTERFACE_ENTRY(it_cbegin) = iterator_cbegin;
|
|
||||||
FX_TYPE_VTABLE_INTERFACE_END(fx_iterable, FX_TYPE_ITERABLE)
|
FX_TYPE_VTABLE_INTERFACE_END(fx_iterable, FX_TYPE_ITERABLE)
|
||||||
FX_TYPE_CLASS_END(fx_directory)
|
FX_TYPE_CLASS_END(fx_directory)
|
||||||
|
|
||||||
@@ -741,7 +730,6 @@ FX_TYPE_CLASS_BEGIN(fx_directory_iterator)
|
|||||||
FX_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
FX_INTERFACE_ENTRY(it_move_next) = iterator_move_next;
|
||||||
FX_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
FX_INTERFACE_ENTRY(it_erase) = iterator_erase;
|
||||||
FX_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
FX_INTERFACE_ENTRY(it_get_value) = iterator_get_value;
|
||||||
FX_INTERFACE_ENTRY(it_get_cvalue) = iterator_get_cvalue;
|
|
||||||
FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
||||||
FX_TYPE_CLASS_END(fx_directory_iterator)
|
FX_TYPE_CLASS_END(fx_directory_iterator)
|
||||||
|
|
||||||
|
|||||||
+10
-3
@@ -392,11 +392,18 @@ void path_fini(fx_object *obj, void *priv)
|
|||||||
fx_string_unref(path->p_pathstr);
|
fx_string_unref(path->p_pathstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_to_string(const fx_object *obj, fx_stream *out)
|
static fx_status path_to_string(
|
||||||
|
const fx_value *obj,
|
||||||
|
fx_stream *out,
|
||||||
|
const char *format)
|
||||||
{
|
{
|
||||||
struct fx_path_p *path = fx_object_get_private(obj, FX_TYPE_PATH);
|
struct fx_path_p *path
|
||||||
|
= fx_object_get_private(obj->v_object, FX_TYPE_PATH);
|
||||||
|
|
||||||
fx_stream_write_cstr(out, fx_string_get_cstr(path->p_pathstr), NULL);
|
return fx_stream_write_cstr(
|
||||||
|
out,
|
||||||
|
fx_string_get_cstr(path->p_pathstr),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** CLASS DEFINITION *********************************************************/
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <fx/type.h>
|
||||||
|
#include <fx/value-type.h>
|
||||||
#include <platform/callvm.h>
|
#include <platform/callvm.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -77,13 +79,88 @@ static void push_double(struct callvm* vm, double value)
|
|||||||
|
|
||||||
void callvm_push(struct callvm *vm, const fx_value *value)
|
void callvm_push(struct callvm *vm, const fx_value *value)
|
||||||
{
|
{
|
||||||
switch (value->v_type.t_primitive) {
|
if (!fx_type_is_value_type(value->v_type)) {
|
||||||
case FX_VALUE_TYPE_DOUBLE:
|
push_int(vm, (uintptr_t)value->v_object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int value_type = __fx_type_get_value_type(value->v_type);
|
||||||
|
|
||||||
|
switch (value_type) {
|
||||||
|
case __FX_VALUE_TYPE_BOOL:
|
||||||
|
push_int(vm, value->v_bool);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I16:
|
||||||
|
push_int(vm, value->v_i16);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U16:
|
||||||
|
push_int(vm, value->v_u16);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I32:
|
||||||
|
push_int(vm, value->v_i32);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U32:
|
||||||
|
push_int(vm, value->v_u32);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I64:
|
||||||
|
push_int(vm, value->v_i64);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U64:
|
||||||
|
push_int(vm, value->v_u64);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_IPTR:
|
||||||
|
push_int(vm, value->v_iptr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_UPTR:
|
||||||
|
push_int(vm, value->v_uptr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SBYTE:
|
||||||
|
push_int(vm, value->v_sbyte);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_BYTE:
|
||||||
|
push_int(vm, value->v_byte);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SHORT:
|
||||||
|
push_int(vm, value->v_short);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_USHORT:
|
||||||
|
push_int(vm, value->v_ushort);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_INT:
|
||||||
|
push_int(vm, value->v_int);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_UINT:
|
||||||
|
push_int(vm, value->v_uint);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_LONG:
|
||||||
|
push_int(vm, value->v_long);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_ULONG:
|
||||||
|
push_int(vm, value->v_ulong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_LONGLONG:
|
||||||
|
push_int(vm, value->v_longlong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_ULONGLONG:
|
||||||
|
push_int(vm, value->v_ulonglong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SIZE:
|
||||||
|
push_int(vm, value->v_size);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_FLOAT:
|
||||||
|
push_double(vm, value->v_float);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_DOUBLE:
|
||||||
push_double(vm, value->v_double);
|
push_double(vm, value->v_double);
|
||||||
break;
|
break;
|
||||||
default:
|
case __FX_VALUE_TYPE_CSTR:
|
||||||
|
push_int(vm, (uintptr_t)value->v_cstr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_POINTER:
|
||||||
push_int(vm, (uintptr_t)value->v_pointer);
|
push_int(vm, (uintptr_t)value->v_pointer);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +171,70 @@ extern void callvm_invoke_v(fx_function_impl impl, struct callvm* vm);
|
|||||||
fx_value callvm_invoke(
|
fx_value callvm_invoke(
|
||||||
struct callvm *vm,
|
struct callvm *vm,
|
||||||
fx_function_impl impl,
|
fx_function_impl impl,
|
||||||
fx_value_type return_type)
|
fx_type_id return_type)
|
||||||
{
|
{
|
||||||
switch (return_type) {
|
if (!fx_type_is_value_type(return_type)) {
|
||||||
case FX_VALUE_TYPE_NONE:
|
uintptr_t v = callvm_invoke_i(impl, vm);
|
||||||
callvm_invoke_v(impl, vm);
|
fx_value result = {
|
||||||
break;
|
.v_type = return_type,
|
||||||
case FX_VALUE_TYPE_DOUBLE:
|
.v_object = (fx_object *)v,
|
||||||
return FX_VALUE_DOUBLE(callvm_invoke_d(impl, vm));
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int value_type = __fx_type_get_value_type(return_type);
|
||||||
|
|
||||||
|
switch (value_type) {
|
||||||
|
case __FX_VALUE_TYPE_BOOL:
|
||||||
|
return FX_BOOL(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I16:
|
||||||
|
return FX_I16(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U16:
|
||||||
|
return FX_U16(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I32:
|
||||||
|
return FX_I32(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U32:
|
||||||
|
return FX_U32(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I64:
|
||||||
|
return FX_I64(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U64:
|
||||||
|
return FX_U64(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_IPTR:
|
||||||
|
return FX_IPTR(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_UPTR:
|
||||||
|
return FX_UPTR(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SBYTE:
|
||||||
|
return FX_SBYTE(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_BYTE:
|
||||||
|
return FX_BYTE(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SHORT:
|
||||||
|
return FX_SHORT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_USHORT:
|
||||||
|
return FX_USHORT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_INT:
|
||||||
|
return FX_INT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_UINT:
|
||||||
|
return FX_UINT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_LONG:
|
||||||
|
return FX_LONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_ULONG:
|
||||||
|
return FX_ULONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_LONGLONG:
|
||||||
|
return FX_LONGLONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_ULONGLONG:
|
||||||
|
return FX_ULONGLONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SIZE:
|
||||||
|
return FX_SIZE(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_FLOAT:
|
||||||
|
return FX_FLOAT(callvm_invoke_d(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_DOUBLE:
|
||||||
|
return FX_DOUBLE(callvm_invoke_d(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_CSTR:
|
||||||
|
return FX_CSTR((const char *)callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_POINTER:
|
||||||
|
return FX_POINTER((void *)callvm_invoke_i(impl, vm));
|
||||||
default:
|
default:
|
||||||
return FX_VALUE_INT(callvm_invoke_i(impl, vm));
|
return FX_VALUE_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FX_VALUE_EMPTY;
|
return FX_VALUE_EMPTY;
|
||||||
|
|||||||
@@ -32,6 +32,6 @@ extern void callvm_push(struct callvm *vm, const fx_value *value);
|
|||||||
extern fx_value callvm_invoke(
|
extern fx_value callvm_invoke(
|
||||||
struct callvm *vm,
|
struct callvm *vm,
|
||||||
fx_function_impl impl,
|
fx_function_impl impl,
|
||||||
fx_value_type return_type);
|
fx_type_id return_type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
.extern memcpy
|
||||||
|
.type memcpy, @function
|
||||||
|
|
||||||
|
.global callvm_invoke_i
|
||||||
|
.type callvm_invoke_i, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm) context
|
||||||
|
callvm_invoke_i:
|
||||||
|
# save the stack frame pointer
|
||||||
|
push %rbp
|
||||||
|
mov %rsp, %rbp
|
||||||
|
|
||||||
|
# store function pointer for later
|
||||||
|
push %r12
|
||||||
|
push %r13
|
||||||
|
push %r14
|
||||||
|
push %r15
|
||||||
|
|
||||||
|
# move our parameters out of the way
|
||||||
|
mov %rdi, %r11
|
||||||
|
mov %rsi, %r12
|
||||||
|
|
||||||
|
# calculate the amount of stack space needed for the varargs
|
||||||
|
movq 32(%r12), %r13
|
||||||
|
shl $3, %r13
|
||||||
|
|
||||||
|
# allocate the stack space
|
||||||
|
push %rsp
|
||||||
|
sub %r13, %rsp
|
||||||
|
andq $0xFFFFFFFFFFFFFFF0, %rsp # re-align the stack
|
||||||
|
|
||||||
|
# copy the excess args to the stack
|
||||||
|
mov %rsp, %rdi
|
||||||
|
mov 160(%r12), %rsi
|
||||||
|
mov %r13, %rdx
|
||||||
|
call memcpy
|
||||||
|
|
||||||
|
# Next, set up the fixed integer arguments
|
||||||
|
|
||||||
|
movq 48(%r12), %rdi # int arg 0
|
||||||
|
movq 56(%r12), %rsi # int arg 1
|
||||||
|
movq 64(%r12), %rdx # int arg 2
|
||||||
|
movq 72(%r12), %rcx # int arg 3
|
||||||
|
movq 80(%r12), %r8 # int arg 4
|
||||||
|
movq 88(%r12), %r9 # int arg 5
|
||||||
|
|
||||||
|
# Finally, set up the fixed double arguments
|
||||||
|
|
||||||
|
movq 96(%r12), %xmm0 # double arg 0
|
||||||
|
movq 104(%r12), %xmm1 # double arg 1
|
||||||
|
movq 112(%r12), %xmm2 # double arg 2
|
||||||
|
movq 120(%r12), %xmm3 # double arg 3
|
||||||
|
movq 128(%r12), %xmm4 # double arg 4
|
||||||
|
movq 136(%r12), %xmm5 # double arg 5
|
||||||
|
movq 144(%r12), %xmm6 # double arg 6
|
||||||
|
movq 152(%r12), %xmm7 # double arg 7
|
||||||
|
|
||||||
|
# set the number of vararg double parameters
|
||||||
|
# as required by the ABI
|
||||||
|
mov 168(%r12), %rax
|
||||||
|
|
||||||
|
# call the function implementation
|
||||||
|
call *%r11
|
||||||
|
|
||||||
|
# Restore the stack pointer (deallocating the varargs buffer)
|
||||||
|
mov -40(%rbp), %rsp
|
||||||
|
|
||||||
|
# Restore callee-saved registers
|
||||||
|
pop %r15
|
||||||
|
pop %r14
|
||||||
|
pop %r13
|
||||||
|
pop %r12
|
||||||
|
|
||||||
|
# restore the saved stack frame
|
||||||
|
pop %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global callvm_invoke_d
|
||||||
|
.type callvm_invoke_d, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm *) context
|
||||||
|
callvm_invoke_d:
|
||||||
|
jmp callvm_invoke_i
|
||||||
|
|
||||||
|
|
||||||
|
.global callvm_invoke_v
|
||||||
|
.type callvm_invoke_v, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm *) context
|
||||||
|
callvm_invoke_v:
|
||||||
|
jmp callvm_invoke_i
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
#include <fx/type.h>
|
||||||
|
#include <fx/value-type.h>
|
||||||
|
#include <platform/callvm.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
switch (arg->v_type.t_primitive) {
|
||||||
|
case FX_VALUE_TYPE_DOUBLE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
callvm_push_int(&vm, (uintptr_t)arg->v_pointer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void callvm_reset(struct callvm *vm, unsigned int max_fixed_args)
|
||||||
|
{
|
||||||
|
vm->vm_arg_int_count = 0;
|
||||||
|
vm->vm_arg_double_count = 0;
|
||||||
|
vm->vm_arg_fixed = max_fixed_args;
|
||||||
|
vm->vm_arg_excess_count = 0;
|
||||||
|
vm->vm_double_excess_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expand_excess(struct callvm *vm)
|
||||||
|
{
|
||||||
|
size_t new_capacity = vm->vm_arg_excess_max * 2;
|
||||||
|
if (!new_capacity) {
|
||||||
|
new_capacity = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buf = realloc(
|
||||||
|
vm->vm_arg_excess,
|
||||||
|
new_capacity * sizeof *vm->vm_arg_excess);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_excess = buf;
|
||||||
|
vm->vm_arg_excess_max = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_excess(struct callvm *vm, uintptr_t value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_excess_count + 1 > vm->vm_arg_excess_max) {
|
||||||
|
expand_excess(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_excess[vm->vm_arg_excess_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_int(struct callvm *vm, uintptr_t value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_int_count >= MAX_INT_ARGS) {
|
||||||
|
push_excess(vm, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_int[vm->vm_arg_int_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_double(struct callvm *vm, double value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_double_count >= MAX_DOUBLE_ARGS) {
|
||||||
|
push_excess(vm, *(uintptr_t *)&value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_double[vm->vm_arg_double_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
|
||||||
|
if (vm->vm_arg_count > vm->vm_arg_fixed) {
|
||||||
|
vm->vm_double_excess_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void callvm_push(struct callvm *vm, const fx_value *value)
|
||||||
|
{
|
||||||
|
if (!fx_type_is_value_type(value->v_type)) {
|
||||||
|
push_int(vm, (uintptr_t)value->v_object);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int value_type = __fx_type_get_value_type(value->v_type);
|
||||||
|
|
||||||
|
switch (value_type) {
|
||||||
|
case __FX_VALUE_TYPE_BOOL:
|
||||||
|
push_int(vm, value->v_bool);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I16:
|
||||||
|
push_int(vm, value->v_i16);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U16:
|
||||||
|
push_int(vm, value->v_u16);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I32:
|
||||||
|
push_int(vm, value->v_i32);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U32:
|
||||||
|
push_int(vm, value->v_u32);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_I64:
|
||||||
|
push_int(vm, value->v_i64);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_U64:
|
||||||
|
push_int(vm, value->v_u64);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_IPTR:
|
||||||
|
push_int(vm, value->v_iptr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_UPTR:
|
||||||
|
push_int(vm, value->v_uptr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SBYTE:
|
||||||
|
push_int(vm, value->v_sbyte);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_BYTE:
|
||||||
|
push_int(vm, value->v_byte);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SHORT:
|
||||||
|
push_int(vm, value->v_short);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_USHORT:
|
||||||
|
push_int(vm, value->v_ushort);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_INT:
|
||||||
|
push_int(vm, value->v_int);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_UINT:
|
||||||
|
push_int(vm, value->v_uint);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_LONG:
|
||||||
|
push_int(vm, value->v_long);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_ULONG:
|
||||||
|
push_int(vm, value->v_ulong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_LONGLONG:
|
||||||
|
push_int(vm, value->v_longlong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_ULONGLONG:
|
||||||
|
push_int(vm, value->v_ulonglong);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_SIZE:
|
||||||
|
push_int(vm, value->v_size);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_FLOAT:
|
||||||
|
push_double(vm, value->v_float);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_DOUBLE:
|
||||||
|
push_double(vm, value->v_double);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_CSTR:
|
||||||
|
push_int(vm, (uintptr_t)value->v_cstr);
|
||||||
|
break;
|
||||||
|
case __FX_VALUE_TYPE_POINTER:
|
||||||
|
push_int(vm, (uintptr_t)value->v_pointer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uintptr_t callvm_invoke_i(fx_function_impl impl, struct callvm *vm);
|
||||||
|
extern double callvm_invoke_d(fx_function_impl impl, struct callvm *vm);
|
||||||
|
extern void callvm_invoke_v(fx_function_impl impl, struct callvm *vm);
|
||||||
|
|
||||||
|
fx_value callvm_invoke(
|
||||||
|
struct callvm *vm,
|
||||||
|
fx_function_impl impl,
|
||||||
|
fx_type_id return_type)
|
||||||
|
{
|
||||||
|
if (!fx_type_is_value_type(return_type)) {
|
||||||
|
uintptr_t v = callvm_invoke_i(impl, vm);
|
||||||
|
fx_value result = {
|
||||||
|
.v_type = return_type,
|
||||||
|
.v_object = (fx_object *)v,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int value_type = __fx_type_get_value_type(return_type);
|
||||||
|
|
||||||
|
switch (value_type) {
|
||||||
|
case __FX_VALUE_TYPE_BOOL:
|
||||||
|
return FX_BOOL(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I16:
|
||||||
|
return FX_I16(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U16:
|
||||||
|
return FX_U16(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I32:
|
||||||
|
return FX_I32(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U32:
|
||||||
|
return FX_U32(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_I64:
|
||||||
|
return FX_I64(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_U64:
|
||||||
|
return FX_U64(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_IPTR:
|
||||||
|
return FX_IPTR(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_UPTR:
|
||||||
|
return FX_UPTR(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SBYTE:
|
||||||
|
return FX_SBYTE(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_BYTE:
|
||||||
|
return FX_BYTE(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SHORT:
|
||||||
|
return FX_SHORT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_USHORT:
|
||||||
|
return FX_USHORT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_INT:
|
||||||
|
return FX_INT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_UINT:
|
||||||
|
return FX_UINT(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_LONG:
|
||||||
|
return FX_LONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_ULONG:
|
||||||
|
return FX_ULONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_LONGLONG:
|
||||||
|
return FX_LONGLONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_ULONGLONG:
|
||||||
|
return FX_ULONGLONG(callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_SIZE:
|
||||||
|
return FX_SIZE(callvm_invoke_i(impl, vm));
|
||||||
|
#if FX_ENABLE_FLOATING_POINT
|
||||||
|
case __FX_VALUE_TYPE_FLOAT:
|
||||||
|
return FX_FLOAT(callvm_invoke_d(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_DOUBLE:
|
||||||
|
return FX_DOUBLE(callvm_invoke_d(impl, vm));
|
||||||
|
#endif
|
||||||
|
case __FX_VALUE_TYPE_CSTR:
|
||||||
|
return FX_CSTR((const char *)callvm_invoke_i(impl, vm));
|
||||||
|
case __FX_VALUE_TYPE_POINTER:
|
||||||
|
return FX_POINTER((void *)callvm_invoke_i(impl, vm));
|
||||||
|
default:
|
||||||
|
return FX_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FX_VALUE_EMPTY;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
#define FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
|
||||||
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAX_FIXED_ARGS ((unsigned int)-1)
|
||||||
|
#define MAX_DOUBLE_ARGS 8
|
||||||
|
#define MAX_INT_ARGS 6
|
||||||
|
|
||||||
|
/* dyn-dispatch.S depends on the layout of this struct */
|
||||||
|
struct callvm {
|
||||||
|
uint64_t vm_arg_int_count;
|
||||||
|
uint64_t vm_arg_double_count;
|
||||||
|
|
||||||
|
/* any args pushed after this limit is reached will be stored in the
|
||||||
|
* excess buffer. used for calling varargs functions */
|
||||||
|
uint64_t vm_arg_count, vm_arg_fixed;
|
||||||
|
|
||||||
|
uint64_t vm_arg_excess_count;
|
||||||
|
uint64_t vm_arg_excess_max;
|
||||||
|
|
||||||
|
uintptr_t vm_arg_int[MAX_INT_ARGS];
|
||||||
|
double vm_arg_double[MAX_DOUBLE_ARGS];
|
||||||
|
uintptr_t *vm_arg_excess;
|
||||||
|
uint64_t vm_double_excess_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void callvm_reset(struct callvm *vm, unsigned int max_fixed_args);
|
||||||
|
extern void callvm_push(struct callvm *vm, const fx_value *value);
|
||||||
|
extern fx_value callvm_invoke(
|
||||||
|
struct callvm *vm,
|
||||||
|
fx_function_impl impl,
|
||||||
|
fx_type_id return_type);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -359,7 +359,7 @@ fx_status cstr_to_size(const char *in, size_t *out)
|
|||||||
return FX_ERR_BAD_STATE;
|
return FX_ERR_BAD_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v > SIZE_T_MAX) {
|
if (v > SIZE_MAX) {
|
||||||
return FX_ERR_BAD_STATE;
|
return FX_ERR_BAD_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,6 +369,7 @@ fx_status cstr_to_size(const char *in, size_t *out)
|
|||||||
|
|
||||||
fx_status cstr_to_float(const char *in, float *out)
|
fx_status cstr_to_float(const char *in, float *out)
|
||||||
{
|
{
|
||||||
|
#if FX_ENABLE_FLOATING_POINT
|
||||||
char *ep;
|
char *ep;
|
||||||
float v = strtof(in, &ep);
|
float v = strtof(in, &ep);
|
||||||
if (*ep) {
|
if (*ep) {
|
||||||
@@ -377,10 +378,14 @@ fx_status cstr_to_float(const char *in, float *out)
|
|||||||
|
|
||||||
*out = v;
|
*out = v;
|
||||||
return FX_SUCCESS;
|
return FX_SUCCESS;
|
||||||
|
#else
|
||||||
|
return FX_ERR_NOT_SUPPORTED;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_status cstr_to_double(const char *in, double *out)
|
fx_status cstr_to_double(const char *in, double *out)
|
||||||
{
|
{
|
||||||
|
#if FX_ENABLE_FLOATING_POINT
|
||||||
char *ep;
|
char *ep;
|
||||||
double v = strtod(in, &ep);
|
double v = strtod(in, &ep);
|
||||||
if (*ep) {
|
if (*ep) {
|
||||||
@@ -389,6 +394,9 @@ fx_status cstr_to_double(const char *in, double *out)
|
|||||||
|
|
||||||
*out = v;
|
*out = v;
|
||||||
return FX_SUCCESS;
|
return FX_SUCCESS;
|
||||||
|
#else
|
||||||
|
return FX_ERR_NOT_SUPPORTED;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_status cstr_to_cstr(const char *in, const char **out)
|
fx_status cstr_to_cstr(const char *in, const char **out)
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
bool fx_wchar_is_number(fx_wchar c)
|
bool fx_wchar_is_number(fx_wchar c)
|
||||||
{
|
{
|
||||||
return iswdigit((wchar_t)c);
|
return (c >= '0' && c <= '9');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fx_wchar_is_alpha(fx_wchar c)
|
bool fx_wchar_is_alpha(fx_wchar c)
|
||||||
|
|||||||
+8
-6
@@ -51,9 +51,8 @@ enum fx_status fx_iterator_move_next(const fx_iterator *it)
|
|||||||
{
|
{
|
||||||
enum fx_status status = FX_ERR_NOT_SUPPORTED;
|
enum fx_status status = FX_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
fx_iterator_class *iface = fx_object_get_interface(
|
fx_iterator_class *iface
|
||||||
it,
|
= fx_object_get_interface(it, FX_TYPE_ITERATOR);
|
||||||
FX_TYPE_ITERATOR);
|
|
||||||
if (iface && iface->it_move_next) {
|
if (iface && iface->it_move_next) {
|
||||||
status = iface->it_move_next(it);
|
status = iface->it_move_next(it);
|
||||||
}
|
}
|
||||||
@@ -66,6 +65,10 @@ enum fx_status fx_iterator_move_next(const fx_iterator *it)
|
|||||||
|
|
||||||
const fx_value *fx_iterator_get_value(const fx_iterator *it)
|
const fx_value *fx_iterator_get_value(const fx_iterator *it)
|
||||||
{
|
{
|
||||||
|
if (fx_iterator_get_status(it) != FX_SUCCESS) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
FX_CLASS_DISPATCH_VIRTUAL_0(
|
FX_CLASS_DISPATCH_VIRTUAL_0(
|
||||||
fx_iterator,
|
fx_iterator,
|
||||||
FX_TYPE_ITERATOR,
|
FX_TYPE_ITERATOR,
|
||||||
@@ -78,9 +81,8 @@ fx_status fx_iterator_erase(fx_iterator *it)
|
|||||||
{
|
{
|
||||||
enum fx_status status = FX_ERR_NOT_SUPPORTED;
|
enum fx_status status = FX_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
fx_iterator_class *iface = fx_object_get_interface(
|
fx_iterator_class *iface
|
||||||
it,
|
= fx_object_get_interface(it, FX_TYPE_ITERATOR);
|
||||||
FX_TYPE_ITERATOR);
|
|
||||||
if (iface && iface->it_erase) {
|
if (iface && iface->it_erase) {
|
||||||
status = iface->it_erase(it);
|
status = iface->it_erase(it);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include <fx/core/bitop.h>
|
#include <fx/bitop.h>
|
||||||
|
|
||||||
int fx_popcountl(long v)
|
int fx_popcountl(long v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,11 +29,13 @@ int main(void)
|
|||||||
printf("%02x", bytes[i % 16]);
|
printf("%02x", bytes[i % 16]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FX_ENABLE_FLOATING_POINT
|
||||||
printf("\n\ngenerating %d random doubles:\n", NRAND_DOUBLES);
|
printf("\n\ngenerating %d random doubles:\n", NRAND_DOUBLES);
|
||||||
for (int i = 0; i < NRAND_DOUBLES; i++) {
|
for (int i = 0; i < NRAND_DOUBLES; i++) {
|
||||||
double v = fx_random_next_double(&random);
|
double v = fx_random_next_double(&random);
|
||||||
printf(" %lf\n", v);
|
printf(" %lf\n", v);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static double another_function(int a, double b, int c)
|
static int another_function(int a, double b, int c)
|
||||||
{
|
{
|
||||||
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
||||||
return 1.2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_function(int a, int b, int c, ...)
|
static int test_function(int a, int b, int c, ...)
|
||||||
|
|||||||
+3
-3
@@ -22,17 +22,17 @@ int main(int argc, const char **argv)
|
|||||||
/* TODO re-implement json support */
|
/* TODO re-implement json support */
|
||||||
fx_serial_ctx *ctx = NULL;
|
fx_serial_ctx *ctx = NULL;
|
||||||
|
|
||||||
fx_object *data;
|
fx_value data = FX_VALUE_EMPTY;
|
||||||
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_object_to_string(data, fx_stdout, NULL);
|
fx_value_to_string(&data, fx_stdout, NULL);
|
||||||
fx_stream_write_char(fx_stdout, '\n');
|
fx_stream_write_char(fx_stdout, '\n');
|
||||||
|
|
||||||
fx_object_unref(data);
|
fx_value_unset(&data);
|
||||||
fx_object_unref(src);
|
fx_object_unref(src);
|
||||||
fx_serial_ctx_unref(ctx);
|
fx_serial_ctx_unref(ctx);
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -22,21 +22,21 @@ int main(int argc, const char **argv)
|
|||||||
|
|
||||||
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
fx_serial_ctx *ctx = fx_toml_serial_ctx_create();
|
||||||
|
|
||||||
fx_object *data = NULL;
|
fx_value data = FX_VALUE_EMPTY;
|
||||||
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
result = fx_serial_ctx_deserialise(ctx, src, &data, 0);
|
||||||
if (fx_result_is_error(result)) {
|
if (fx_result_is_error(result)) {
|
||||||
fx_throw(result);
|
fx_throw(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data) {
|
if (!fx_value_is_set(&data)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fx_object_to_string(data, fx_stdout, NULL);
|
fx_value_to_string(&data, fx_stdout, NULL);
|
||||||
fx_stream_write_char(fx_stdout, '\n');
|
fx_stream_write_char(fx_stdout, '\n');
|
||||||
|
|
||||||
fx_object_unref(data);
|
fx_value_unset(&data);
|
||||||
fx_object_unref(src);
|
fx_object_unref(src);
|
||||||
fx_serial_ctx_unref(ctx);
|
fx_serial_ctx_unref(ctx);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user