aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rwxr-xr-x[-rw-r--r--]system/include/emscripten/bind.h1311
-rw-r--r--system/include/emscripten/val.h259
-rwxr-xr-x[-rw-r--r--]system/include/emscripten/wire.h297
-rw-r--r--system/lib/compiler-rt/LICENSE.TXT97
-rw-r--r--system/lib/compiler-rt/divdi3.c47
-rw-r--r--system/lib/compiler-rt/int_endianness.h116
-rw-r--r--system/lib/compiler-rt/int_lib.h46
-rw-r--r--system/lib/compiler-rt/int_math.h67
-rw-r--r--system/lib/compiler-rt/int_types.h140
-rw-r--r--system/lib/compiler-rt/int_util.h29
-rw-r--r--system/lib/compiler-rt/muldi3.c56
-rw-r--r--system/lib/compiler-rt/readme.txt20
-rw-r--r--system/lib/compiler-rt/udivdi3.c36
-rw-r--r--system/lib/compiler-rt/udivmoddi4.c251
-rwxr-xr-xsystem/lib/embind/bind.cpp100
15 files changed, 2354 insertions, 518 deletions
diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h
index 55fda986..4d2f4ac8 100644..100755
--- a/system/include/emscripten/bind.h
+++ b/system/include/emscripten/bind.h
@@ -3,11 +3,20 @@
#include <stddef.h>
#include <assert.h>
#include <string>
+#include <functional>
+#include <vector>
+#include <map>
#include <type_traits>
#include <emscripten/val.h>
#include <emscripten/wire.h>
namespace emscripten {
+ enum class sharing_policy {
+ NONE = 0,
+ INTRUSIVE = 1,
+ BY_EMVAL = 2,
+ };
+
namespace internal {
typedef void (*GenericFunction)();
typedef long GenericEnumValue;
@@ -19,150 +28,224 @@ namespace emscripten {
const char* payload) __attribute__((noreturn));
void _embind_register_void(
- TypeID voidType,
+ TYPEID voidType,
const char* name);
void _embind_register_bool(
- TypeID boolType,
+ TYPEID boolType,
const char* name,
bool trueValue,
bool falseValue);
void _embind_register_integer(
- TypeID integerType,
- const char* name);
+ TYPEID integerType,
+ const char* name,
+ long minRange,
+ unsigned long maxRange);
void _embind_register_float(
- TypeID floatType,
+ TYPEID floatType,
const char* name);
- void _embind_register_cstring(
- TypeID stringType,
+ void _embind_register_std_string(
+ TYPEID stringType,
+ const char* name);
+
+ void _embind_register_std_wstring(
+ TYPEID stringType,
+ size_t charSize,
const char* name);
void _embind_register_emval(
- TypeID emvalType,
+ TYPEID emvalType,
const char* name);
void _embind_register_function(
const char* name,
- TypeID returnType,
unsigned argCount,
- TypeID argTypes[],
+ TYPEID argTypes[],
GenericFunction invoker,
GenericFunction function);
void _embind_register_tuple(
- TypeID tupleType,
+ TYPEID tupleType,
const char* name,
GenericFunction constructor,
GenericFunction destructor);
void _embind_register_tuple_element(
- TypeID tupleType,
- TypeID elementType,
+ TYPEID tupleType,
+ TYPEID getterReturnType,
GenericFunction getter,
+ void* getterContext,
+ TYPEID setterArgumentType,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
-
- void _embind_register_tuple_element_accessor(
- TypeID tupleType,
- TypeID elementType,
- GenericFunction staticGetter,
- size_t getterSize,
- void* getter,
- GenericFunction staticSetter,
- size_t setterSize,
- void* setter);
+ void* setterContext);
+
+ void _embind_finalize_tuple(TYPEID tupleType);
void _embind_register_struct(
- TypeID structType,
- const char* name,
+ TYPEID structType,
+ const char* fieldName,
GenericFunction constructor,
GenericFunction destructor);
void _embind_register_struct_field(
- TypeID structType,
- const char* name,
- TypeID fieldType,
+ TYPEID structType,
+ const char* fieldName,
+ TYPEID getterReturnType,
GenericFunction getter,
+ void* getterContext,
+ TYPEID setterArgumentType,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
+ void* setterContext);
+
+ void _embind_finalize_struct(TYPEID structType);
+
+ void _embind_register_smart_ptr(
+ TYPEID pointerType,
+ TYPEID pointeeType,
+ const char* pointerName,
+ sharing_policy sharingPolicy,
+ GenericFunction getPointee,
+ GenericFunction constructor,
+ GenericFunction share,
+ GenericFunction destructor);
void _embind_register_class(
- TypeID classType,
+ TYPEID classType,
+ TYPEID pointerType,
+ TYPEID constPointerType,
+ TYPEID baseClassType,
+ GenericFunction getActualType,
+ GenericFunction upcast,
+ GenericFunction downcast,
const char* className,
GenericFunction destructor);
void _embind_register_class_constructor(
- TypeID classType,
+ TYPEID classType,
unsigned argCount,
- TypeID argTypes[],
+ TYPEID argTypes[],
+ GenericFunction invoker,
GenericFunction constructor);
- void _embind_register_class_method(
- TypeID classType,
+ void _embind_register_class_function(
+ TYPEID classType,
const char* methodName,
- TypeID returnType,
unsigned argCount,
- TypeID argTypes[],
+ TYPEID argTypes[],
GenericFunction invoker,
- size_t memberFunctionSize,
- void* memberFunction);
+ void* context);
- void _embind_register_class_field(
- TypeID classType,
+ void _embind_register_class_property(
+ TYPEID classType,
const char* fieldName,
- TypeID fieldType,
+ TYPEID getterReturnType,
GenericFunction getter,
+ void* getterContext,
+ TYPEID setterArgumentType,
GenericFunction setter,
- size_t memberPointerSize,
- void* memberPointer);
+ void* setterContext);
- void _embind_register_class_classmethod(
- TypeID classType,
+ void _embind_register_class_class_function(
+ TYPEID classType,
const char* methodName,
- TypeID returnType,
unsigned argCount,
- TypeID argTypes[],
+ TYPEID argTypes[],
+ GenericFunction invoker,
GenericFunction method);
void _embind_register_enum(
- TypeID enumType,
+ TYPEID enumType,
const char* name);
void _embind_register_enum_value(
- TypeID enumType,
+ TYPEID enumType,
const char* valueName,
GenericEnumValue value);
void _embind_register_interface(
- TypeID interfaceType,
+ TYPEID interfaceType,
const char* name,
GenericFunction constructor,
GenericFunction destructor);
+
+ void _embind_register_constant(
+ const char* name,
+ TYPEID constantType,
+ uintptr_t value);
}
+ }
+}
- extern void registerStandardTypes();
+namespace emscripten {
+ ////////////////////////////////////////////////////////////////////////////////
+ // POLICIES
+ ////////////////////////////////////////////////////////////////////////////////
- class BindingsDefinition {
- public:
- template<typename Function>
- BindingsDefinition(Function fn) {
- fn();
- }
+ template<int Index>
+ struct arg {
+ static constexpr int index = Index + 1;
+ };
+
+ struct ret_val {
+ static constexpr int index = 0;
+ };
+
+ /*
+ template<typename Slot>
+ struct allow_raw_pointer {
+ template<typename InputType, int Index>
+ struct Transform {
+ typedef typename std::conditional<
+ Index == Slot::index,
+ internal::AllowedRawPointer<typename std::remove_pointer<InputType>::type>,
+ InputType
+ >::type type;
+ };
+ };
+ */
+
+ // whitelist all raw pointers
+ struct allow_raw_pointers {
+ template<typename InputType, int Index>
+ struct Transform {
+ typedef typename std::conditional<
+ std::is_pointer<InputType>::value,
+ internal::AllowedRawPointer<typename std::remove_pointer<InputType>::type>,
+ InputType
+ >::type type;
};
+ };
+
+ // this is temporary until arg policies are reworked
+ template<typename Slot>
+ struct allow_raw_pointer : public allow_raw_pointers {
+ };
+
+ template<typename Signature>
+ typename std::add_pointer<Signature>::type select_overload(typename std::add_pointer<Signature>::type fn) {
+ return fn;
+ }
+
+ namespace internal {
+ template<typename ClassType, typename Signature>
+ struct MemberFunctionType {
+ typedef Signature (ClassType::*type);
+ };
+ }
+
+ template<typename Signature, typename ClassType>
+ typename internal::MemberFunctionType<ClassType, Signature>::type select_overload(Signature (ClassType::*fn)) {
+ return fn;
}
-}
-namespace emscripten {
namespace internal {
template<typename ReturnType, typename... Args>
struct Invoker {
static typename internal::BindingType<ReturnType>::WireType invoke(
- ReturnType (fn)(Args...),
+ ReturnType (*fn)(Args...),
typename internal::BindingType<Args>::WireType... args
) {
return internal::BindingType<ReturnType>::toWireType(
@@ -176,7 +259,7 @@ namespace emscripten {
template<typename... Args>
struct Invoker<void, Args...> {
static void invoke(
- void (fn)(Args...),
+ void (*fn)(Args...),
typename internal::BindingType<Args>::WireType... args
) {
return fn(
@@ -186,22 +269,38 @@ namespace emscripten {
};
}
- template<typename ReturnType, typename... Args>
- void function(const char* name, ReturnType (fn)(Args...)) {
- internal::registerStandardTypes();
+ ////////////////////////////////////////////////////////////////////////////////
+ // FUNCTIONS
+ ////////////////////////////////////////////////////////////////////////////////
+
+ extern "C" {
+ void* __getDynamicPointerType(void* p);
+ }
- internal::ArgTypeList<Args...> args;
- internal::_embind_register_function(
+ template<typename ReturnType, typename... Args, typename... Policies>
+ void function(const char* name, ReturnType (*fn)(Args...), Policies...) {
+ using namespace internal;
+ typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
+ _embind_register_function(
name,
- internal::getTypeID<ReturnType>(),
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(&internal::Invoker<ReturnType, Args...>::invoke),
- reinterpret_cast<internal::GenericFunction>(fn));
+ reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke),
+ reinterpret_cast<GenericFunction>(fn));
}
namespace internal {
template<typename ClassType, typename... Args>
+ ClassType* operator_new(Args... args) {
+ return new ClassType(args...);
+ }
+
+ template<typename WrapperType, typename ClassType, typename... Args>
+ WrapperType wrapped_new(Args&&... args) {
+ return WrapperType(new ClassType(std::forward<Args>(args)...));
+ }
+
+ template<typename ClassType, typename... Args>
ClassType* raw_constructor(
typename internal::BindingType<Args>::WireType... args
) {
@@ -215,302 +314,871 @@ namespace emscripten {
delete ptr;
}
- template<typename ClassType, typename ReturnType, typename... Args>
- struct MethodInvoker {
- typedef ReturnType (ClassType::*MemberPointer)(Args...);
+ template<typename FunctionPointerType, typename ReturnType, typename ThisType, typename... Args>
+ struct FunctionInvoker {
static typename internal::BindingType<ReturnType>::WireType invoke(
- ClassType* ptr,
- const MemberPointer& method,
+ FunctionPointerType* function,
+ typename internal::BindingType<ThisType>::WireType wireThis,
typename internal::BindingType<Args>::WireType... args
) {
return internal::BindingType<ReturnType>::toWireType(
- (ptr->*method)(
- internal::BindingType<Args>::fromWireType(args)...
- )
+ (*function)(
+ internal::BindingType<ThisType>::fromWireType(wireThis),
+ internal::BindingType<Args>::fromWireType(args)...)
);
}
};
- template<typename ClassType, typename... Args>
- struct MethodInvoker<ClassType, void, Args...> {
- typedef void (ClassType::*MemberPointer)(Args...);
+ template<typename FunctionPointerType, typename ThisType, typename... Args>
+ struct FunctionInvoker<FunctionPointerType, void, ThisType, Args...> {
static void invoke(
- ClassType* ptr,
- const MemberPointer& method,
+ FunctionPointerType* function,
+ typename internal::BindingType<ThisType>::WireType wireThis,
typename internal::BindingType<Args>::WireType... args
) {
- return (ptr->*method)(
- internal::BindingType<Args>::fromWireType(args)...
- );
+ (*function)(
+ internal::BindingType<ThisType>::fromWireType(wireThis),
+ internal::BindingType<Args>::fromWireType(args)...);
}
};
- template<typename ClassType, typename ReturnType, typename... Args>
- struct ConstMethodInvoker {
- typedef ReturnType (ClassType::*MemberPointer)(Args...) const;
+ template<typename MemberPointer,
+ typename ReturnType,
+ typename ThisType,
+ typename... Args>
+ struct MethodInvoker {
static typename internal::BindingType<ReturnType>::WireType invoke(
- const ClassType* ptr,
const MemberPointer& method,
+ typename internal::BindingType<ThisType>::WireType wireThis,
typename internal::BindingType<Args>::WireType... args
) {
return internal::BindingType<ReturnType>::toWireType(
- (ptr->*method)(
+ (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)(
internal::BindingType<Args>::fromWireType(args)...
)
);
}
};
- template<typename ClassType, typename... Args>
- struct ConstMethodInvoker<ClassType, void, Args...> {
- typedef void (ClassType::*MemberPointer)(Args...) const;
+ template<typename MemberPointer,
+ typename ThisType,
+ typename... Args>
+ struct MethodInvoker<MemberPointer, void, ThisType, Args...> {
static void invoke(
- const ClassType* ptr,
const MemberPointer& method,
+ typename internal::BindingType<ThisType>::WireType wireThis,
typename internal::BindingType<Args>::WireType... args
) {
- return (ptr->*method)(
+ return (internal::BindingType<ThisType>::fromWireType(wireThis)->*method)(
internal::BindingType<Args>::fromWireType(args)...
);
}
};
- template<typename ClassType, typename FieldType>
- struct FieldAccess {
- typedef FieldType ClassType::*MemberPointer;
- typedef internal::BindingType<FieldType> FieldBinding;
- typedef typename FieldBinding::WireType WireType;
+ template<typename InstanceType, typename MemberType>
+ struct MemberAccess {
+ typedef MemberType InstanceType::*MemberPointer;
+ typedef internal::BindingType<MemberType> MemberBinding;
+ typedef typename MemberBinding::WireType WireType;
- static WireType get(
- ClassType& ptr,
- const MemberPointer& field
+ template<typename ClassType>
+ static WireType getWire(
+ const MemberPointer& field,
+ const ClassType& ptr
) {
- return FieldBinding::toWireType(ptr.*field);
+ return MemberBinding::toWireType(ptr.*field);
}
- static void set(
- ClassType& ptr,
+ template<typename ClassType>
+ static void setWire(
const MemberPointer& field,
+ ClassType& ptr,
WireType value
) {
- ptr.*field = FieldBinding::fromWireType(value);
+ ptr.*field = MemberBinding::fromWireType(value);
}
+ };
- template<typename Getter>
- static WireType propertyGet(
- ClassType& ptr,
- const Getter& getter
- ) {
- return FieldBinding::toWireType(getter(ptr));
+ // TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*)
+ template<typename T>
+ inline void* getContext(const T& t) {
+ // not a leak because this is called once per binding
+ void* p = malloc(sizeof(T));
+ assert(p);
+ memcpy(p, &t, sizeof(T));
+ return p;
+ }
+
+ template<typename T>
+ struct GetterPolicy;
+
+ template<typename GetterReturnType, typename GetterThisType>
+ struct GetterPolicy<GetterReturnType (GetterThisType::*)() const> {
+ typedef GetterReturnType ReturnType;
+ typedef GetterReturnType (GetterThisType::*Context)() const;
+
+ typedef internal::BindingType<ReturnType> Binding;
+ typedef typename Binding::WireType WireType;
+
+ template<typename ClassType>
+ static WireType get(const Context& context, const ClassType& ptr) {
+ return Binding::toWireType((ptr.*context)());
}
- template<typename Setter>
- static void propertySet(
- ClassType& ptr,
- const Setter& setter,
- WireType value
- ) {
- setter(ptr, FieldBinding::fromWireType(value));
+ static void* getContext(Context context) {
+ return internal::getContext(context);
+ }
+ };
+
+ template<typename GetterReturnType, typename GetterThisType>
+ struct GetterPolicy<GetterReturnType (*)(const GetterThisType&)> {
+ typedef GetterReturnType ReturnType;
+ typedef GetterReturnType (*Context)(const GetterThisType&);
+
+ typedef internal::BindingType<ReturnType> Binding;
+ typedef typename Binding::WireType WireType;
+
+ template<typename ClassType>
+ static WireType get(const Context& context, const ClassType& ptr) {
+ return Binding::toWireType(context(ptr));
+ }
+
+ static void* getContext(Context context) {
+ return internal::getContext(context);
+ }
+ };
+
+ template<typename T>
+ struct SetterPolicy;
+
+ template<typename SetterThisType, typename SetterArgumentType>
+ struct SetterPolicy<void (SetterThisType::*)(SetterArgumentType)> {
+ typedef SetterArgumentType ArgumentType;
+ typedef void (SetterThisType::*Context)(SetterArgumentType);
+
+ typedef internal::BindingType<SetterArgumentType> Binding;
+ typedef typename Binding::WireType WireType;
+
+ template<typename ClassType>
+ static void set(const Context& context, ClassType& ptr, WireType wt) {
+ (ptr.*context)(Binding::fromWireType(wt));
+ }
+
+ static void* getContext(Context context) {
+ return internal::getContext(context);
+ }
+ };
+
+ template<typename SetterThisType, typename SetterArgumentType>
+ struct SetterPolicy<void (*)(SetterThisType&, SetterArgumentType)> {
+ typedef SetterArgumentType ArgumentType;
+ typedef void (*Context)(SetterThisType&, SetterArgumentType);
+
+ typedef internal::BindingType<SetterArgumentType> Binding;
+ typedef typename Binding::WireType WireType;
+
+ template<typename ClassType>
+ static void set(const Context& context, ClassType& ptr, WireType wt) {
+ context(ptr, Binding::fromWireType(wt));
+ }
+
+ static void* getContext(Context context) {
+ return internal::getContext(context);
}
};
+
+ class noncopyable {
+ protected:
+ noncopyable() {}
+ ~noncopyable() {}
+ private:
+ noncopyable(const noncopyable&) = delete;
+ const noncopyable& operator=(const noncopyable&) = delete;
+ };
+
+ template<typename ClassType, typename ElementType>
+ typename BindingType<ElementType>::WireType get_by_index(int index, ClassType& ptr) {
+ return BindingType<ElementType>::toWireType(ptr[index]);
+ }
+
+ template<typename ClassType, typename ElementType>
+ void set_by_index(int index, ClassType& ptr, typename BindingType<ElementType>::WireType wt) {
+ ptr[index] = BindingType<ElementType>::fromWireType(wt);
+ }
}
+ template<int Index>
+ struct index {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // VALUE TUPLES
+ ////////////////////////////////////////////////////////////////////////////////
+
template<typename ClassType>
- class value_tuple {
+ class value_tuple : public internal::noncopyable {
public:
value_tuple(const char* name) {
- internal::registerStandardTypes();
- internal::_embind_register_tuple(
- internal::getTypeID<ClassType>(),
+ using namespace internal;
+ _embind_register_tuple(
+ TypeID<ClassType>::get(),
name,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
- }
-
- template<typename ElementType>
- value_tuple& element(ElementType ClassType::*field) {
- internal::_embind_register_tuple_element(
- internal::getTypeID<ClassType>(),
- internal::getTypeID<ElementType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::get),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::set),
- sizeof(field),
- &field);
-
- return *this;
+ reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
+ reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
}
- template<typename ElementType>
- value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType)) {
- internal::_embind_register_tuple_element_accessor(
- internal::getTypeID<ClassType>(),
- internal::getTypeID<ElementType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
- return *this;
+ ~value_tuple() {
+ using namespace internal;
+ _embind_finalize_tuple(TypeID<ClassType>::get());
}
- template<typename ElementType>
- value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::getTypeID<ClassType>(),
- internal::getTypeID<ElementType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ template<typename InstanceType, typename ElementType>
+ value_tuple& element(ElementType InstanceType::*field) {
+ using namespace internal;
+ _embind_register_tuple_element(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(
+ &MemberAccess<InstanceType, ElementType>
+ ::template getWire<ClassType>),
+ getContext(field),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(
+ &MemberAccess<InstanceType, ElementType>
+ ::template setWire<ClassType>),
+ getContext(field));
return *this;
}
- template<typename ElementType>
- value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, const ElementType&&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::getTypeID<ClassType>(),
- internal::getTypeID<ElementType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ template<typename Getter, typename Setter>
+ value_tuple& element(Getter getter, Setter setter) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ typedef SetterPolicy<Setter> SP;
+ _embind_register_tuple_element(
+ TypeID<ClassType>::get(),
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ TypeID<typename SP::ArgumentType>::get(),
+ reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ SP::getContext(setter));
return *this;
}
- template<typename ElementType>
- value_tuple& element(ElementType (*getter)(const ClassType&), void (*setter)(ClassType&, ElementType&)) {
- internal::_embind_register_tuple_element_accessor(
- internal::getTypeID<ClassType>(),
- internal::getTypeID<ElementType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertyGet<ElementType(const ClassType&)>),
- sizeof(getter),
- &getter,
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, ElementType>::template propertySet<void(ClassType&, ElementType)>),
- sizeof(setter),
- &setter);
+ template<int Index>
+ value_tuple& element(index<Index>) {
+ using namespace internal;
+ ClassType* null = 0;
+ typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType;
+ _embind_register_tuple_element(
+ TypeID<ClassType>::get(),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>),
+ reinterpret_cast<void*>(Index),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>),
+ reinterpret_cast<void*>(Index));
return *this;
}
};
+ ////////////////////////////////////////////////////////////////////////////////
+ // VALUE STRUCTS
+ ////////////////////////////////////////////////////////////////////////////////
+
template<typename ClassType>
- class value_struct {
+ class value_struct : public internal::noncopyable {
public:
value_struct(const char* name) {
- internal::registerStandardTypes();
- internal::_embind_register_struct(
- internal::getTypeID<ClassType>(),
+ using namespace internal;
+ _embind_register_struct(
+ TypeID<ClassType>::get(),
name,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType>),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ reinterpret_cast<GenericFunction>(&raw_constructor<ClassType>),
+ reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
+ }
+
+ ~value_struct() {
+ _embind_finalize_struct(internal::TypeID<ClassType>::get());
+ }
+
+ template<typename InstanceType, typename FieldType>
+ value_struct& field(const char* fieldName, FieldType InstanceType::*field) {
+ using namespace internal;
+ _embind_register_struct_field(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(
+ &MemberAccess<InstanceType, FieldType>
+ ::template getWire<ClassType>),
+ getContext(field),
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(
+ &MemberAccess<InstanceType, FieldType>
+ ::template setWire<ClassType>),
+ getContext(field));
+ return *this;
+ }
+
+ template<typename Getter, typename Setter>
+ value_struct& field(
+ const char* fieldName,
+ Getter getter,
+ Setter setter
+ ) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ typedef SetterPolicy<Setter> SP;
+ _embind_register_struct_field(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ TypeID<typename SP::ArgumentType>::get(),
+ reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ SP::getContext(setter));
+ return *this;
}
- template<typename FieldType>
- value_struct& field(const char* fieldName, FieldType ClassType::*field) {
- internal::_embind_register_struct_field(
- internal::getTypeID<ClassType>(),
+ template<int Index>
+ value_struct& field(const char* fieldName, index<Index>) {
+ using namespace internal;
+ ClassType* null = 0;
+ typedef typename std::remove_reference<decltype((*null)[Index])>::type ElementType;
+ _embind_register_struct_field(
+ TypeID<ClassType>::get(),
fieldName,
- internal::getTypeID<FieldType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::get),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::set),
- sizeof(field),
- &field);
-
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&internal::get_by_index<ClassType, ElementType>),
+ reinterpret_cast<void*>(Index),
+ TypeID<ElementType>::get(),
+ reinterpret_cast<GenericFunction>(&internal::set_by_index<ClassType, ElementType>),
+ reinterpret_cast<void*>(Index));
return *this;
}
};
- // TODO: support class definitions without constructors.
- // TODO: support external class constructors
- template<typename ClassType>
+ ////////////////////////////////////////////////////////////////////////////////
+ // SMART POINTERS
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template<typename PointerType>
+ struct default_smart_ptr_trait {
+ static sharing_policy get_sharing_policy() {
+ return sharing_policy::NONE;
+ }
+
+ static void* share(void* v) {
+ return 0; // no sharing
+ }
+ };
+
+ // specialize if you have a different pointer type
+ template<typename PointerType>
+ struct smart_ptr_trait : public default_smart_ptr_trait<PointerType> {
+ typedef typename PointerType::element_type element_type;
+
+ static element_type* get(const PointerType& ptr) {
+ return ptr.get();
+ }
+ };
+
+ template<typename PointeeType>
+ struct smart_ptr_trait<std::shared_ptr<PointeeType>> {
+ typedef std::shared_ptr<PointeeType> PointerType;
+ typedef typename PointerType::element_type element_type;
+
+ static element_type* get(const PointerType& ptr) {
+ return ptr.get();
+ }
+
+ static sharing_policy get_sharing_policy() {
+ return sharing_policy::BY_EMVAL;
+ }
+
+ static std::shared_ptr<PointeeType>* share(PointeeType* p, internal::EM_VAL v) {
+ return new std::shared_ptr<PointeeType>(
+ p,
+ val_deleter(val::take_ownership(v)));
+ }
+
+ private:
+ class val_deleter {
+ public:
+ val_deleter() = delete;
+ explicit val_deleter(val v)
+ : v(v)
+ {}
+ void operator()(void const*) {
+ v();
+ // eventually we'll need to support emptied out val
+ v = val::undefined();
+ }
+ private:
+ val v;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // CLASSES
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // abstract classes
+ template<typename T>
+ class wrapper : public T {
+ public:
+ explicit wrapper(val&& wrapped)
+ : wrapped(std::forward<val>(wrapped))
+ {}
+
+ template<typename ReturnType, typename... Args>
+ ReturnType call(const char* name, Args&&... args) const {
+ return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ }
+
+ template<typename ReturnType, typename... Args, typename Default>
+ ReturnType optional_call(const char* name, Default def, Args&&... args) const {
+ if (has_function(name)) {
+ return Caller<ReturnType, Args...>::call(wrapped, name, std::forward<Args>(args)...);
+ } else {
+ return def();
+ }
+ }
+
+ private:
+ bool has_function(const char* name) const {
+ return wrapped.has_function(name);
+ }
+
+ // this class only exists because you can't partially specialize function templates
+ template<typename ReturnType, typename... Args>
+ struct Caller {
+ static ReturnType call(const val& v, const char* name, Args&&... args) {
+ return v.call(name, std::forward<Args>(args)...).template as<ReturnType>();
+ }
+ };
+
+ template<typename... Args>
+ struct Caller<void, Args...> {
+ static void call(const val& v, const char* name, Args&&... args) {
+ v.call_void(name, std::forward<Args>(args)...);
+ }
+ };
+
+ val wrapped;
+ };
+
+#define EMSCRIPTEN_WRAPPER(T) \
+ T(::emscripten::val&& v): wrapper(std::forward<::emscripten::val>(v)) {}
+
+ namespace internal {
+ struct NoBaseClass {
+ template<typename ClassType>
+ static void verify() {
+ }
+
+ static TYPEID get() {
+ return nullptr;
+ }
+
+ template<typename ClassType>
+ static GenericFunction getUpcaster() {
+ return nullptr;
+ }
+
+ template<typename ClassType>
+ static GenericFunction getDowncaster() {
+ return nullptr;
+ }
+ };
+
+ // NOTE: this returns the class type, not the pointer type
+ template<typename T>
+ inline TYPEID getActualType(T* ptr) {
+ assert(ptr);
+ return reinterpret_cast<TYPEID>(&typeid(*ptr));
+ };
+ }
+
+ template<typename BaseClass>
+ struct base {
+ template<typename ClassType>
+ static void verify() {
+ static_assert(!std::is_same<ClassType, BaseClass>::value, "Base must not have same type as class");
+ static_assert(std::is_base_of<BaseClass, ClassType>::value, "Derived class must derive from base");
+ }
+
+ static internal::TYPEID get() {
+ return internal::TypeID<BaseClass>::get();
+ }
+
+ template<typename ClassType>
+ static internal::GenericFunction getUpcaster() {
+ return reinterpret_cast<internal::GenericFunction>(&convertPointer<ClassType, BaseClass>);
+ }
+
+ template<typename ClassType>
+ static internal::GenericFunction getDowncaster() {
+ return reinterpret_cast<internal::GenericFunction>(&convertPointer<BaseClass, ClassType>);
+ }
+
+ template<typename From, typename To>
+ static To* convertPointer(From* ptr) {
+ return static_cast<To*>(ptr);
+ }
+ };
+
+ template<typename PointerType>
+ struct ptr {
+ typedef PointerType pointer_type;
+ };
+
+ namespace internal {
+ template<typename T>
+ struct is_ptr {
+ enum { value = false };
+ };
+
+ template<typename T>
+ struct is_ptr<ptr<T>> {
+ enum { value = true };
+ };
+
+ template<typename T>
+ struct SmartPtrIfNeeded {
+ template<typename U>
+ SmartPtrIfNeeded(U& cls) {
+ cls.template smart_ptr<T>();
+ }
+ };
+
+ template<typename T>
+ struct SmartPtrIfNeeded<T*> {
+ template<typename U>
+ SmartPtrIfNeeded(U&) {
+ }
+ };
+ };
+
+ template<typename ClassType, typename BaseSpecifier = internal::NoBaseClass>
class class_ {
public:
- class_(const char* name) {
- internal::registerStandardTypes();
- internal::_embind_register_class(
- internal::getTypeID<ClassType>(),
+ class_() = delete;
+
+ template<typename = typename std::enable_if<!internal::is_ptr<ClassType>::value>::type>
+ explicit class_(const char* name) {
+ using namespace internal;
+
+ BaseSpecifier::template verify<ClassType>();
+
+ _embind_register_class(
+ TypeID<ClassType>::get(),
+ TypeID<AllowedRawPointer<ClassType>>::get(),
+ TypeID<AllowedRawPointer<const ClassType>>::get(),
+ BaseSpecifier::get(),
+ reinterpret_cast<GenericFunction>(&getActualType<ClassType>),
+ BaseSpecifier::template getUpcaster<ClassType>(),
+ BaseSpecifier::template getDowncaster<ClassType>(),
name,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<ClassType>));
+ reinterpret_cast<GenericFunction>(&raw_destructor<ClassType>));
+ }
+
+ template<typename PointerType>
+ class_& smart_ptr() {
+ using namespace internal;
+
+ typedef smart_ptr_trait<PointerType> PointerTrait;
+ typedef typename PointerTrait::element_type PointeeType;
+
+ static_assert(std::is_same<ClassType, typename std::remove_cv<PointeeType>::type>::value, "smart pointer must point to this class");
+
+ _embind_register_smart_ptr(
+ TypeID<PointerType>::get(),
+ TypeID<PointeeType>::get(),
+ typeid(PointerType).name(),
+ PointerTrait::get_sharing_policy(),
+ reinterpret_cast<GenericFunction>(&PointerTrait::get),
+ reinterpret_cast<GenericFunction>(&operator_new<PointerType>),
+ reinterpret_cast<GenericFunction>(&PointerTrait::share),
+ reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>));
+ return *this;
+ };
+
+ template<typename... ConstructorArgs, typename... Policies>
+ class_& constructor(Policies... policies) {
+ return constructor(
+ &internal::operator_new<ClassType, ConstructorArgs...>,
+ policies...);
}
- template<typename... ConstructorArgs>
- class_& constructor() {
- internal::ArgTypeList<ConstructorArgs...> args;
- internal::_embind_register_class_constructor(
- internal::getTypeID<ClassType>(),
+ template<typename... Args, typename... Policies>
+ class_& constructor(ClassType* (*factory)(Args...), Policies...) {
+ using namespace internal;
+
+ typename WithPolicies<Policies...>::template ArgTypeList<AllowedRawPointer<ClassType>, Args...> args;
+ _embind_register_class_constructor(
+ TypeID<ClassType>::get(),
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(&internal::raw_constructor<ClassType, ConstructorArgs...>));
+ reinterpret_cast<GenericFunction>(&Invoker<ClassType*, Args...>::invoke),
+ reinterpret_cast<GenericFunction>(factory));
return *this;
}
- template<typename ReturnType, typename... Args>
- class_& method(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...)) {
- internal::ArgTypeList<Args...> args;
- internal::_embind_register_class_method(
- internal::getTypeID<ClassType>(),
+ template<typename SmartPtr, typename... Args, typename... Policies>
+ class_& smart_ptr_constructor(SmartPtr (*factory)(Args...), Policies...) {
+ using namespace internal;
+
+ smart_ptr<SmartPtr>();
+
+ typename WithPolicies<Policies...>::template ArgTypeList<SmartPtr, Args...> args;
+ _embind_register_class_constructor(
+ TypeID<ClassType>::get(),
+ args.count,
+ args.types,
+ reinterpret_cast<GenericFunction>(&Invoker<SmartPtr, Args...>::invoke),
+ reinterpret_cast<GenericFunction>(factory));
+ return *this;
+ }
+
+ template<typename WrapperType, typename PointerType = WrapperType*>
+ class_& allow_subclass() {
+ using namespace internal;
+
+ auto cls = class_<WrapperType, base<ClassType>>(typeid(WrapperType).name())
+ ;
+ SmartPtrIfNeeded<PointerType> _(cls);
+
+ return class_function(
+ "implement",
+ &wrapped_new<PointerType, WrapperType, val>,
+ allow_raw_pointer<ret_val>());
+ }
+
+ template<typename ReturnType, typename... Args, typename... Policies>
+ class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) {
+ using namespace internal;
+
+ typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<ClassType>, Args...> args;
+ _embind_register_class_function(
+ TypeID<ClassType>::get(),
methodName,
- internal::getTypeID<ReturnType>(),
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(&internal::MethodInvoker<ClassType, ReturnType, Args...>::invoke),
- sizeof(memberFunction),
- &memberFunction);
+ reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, ClassType*, Args...>::invoke),
+ getContext(memberFunction));
return *this;
}
- template<typename ReturnType, typename... Args>
- class_& method(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const) {
- internal::ArgTypeList<Args...> args;
- internal::_embind_register_class_method(
- internal::getTypeID<ClassType>(),
+ template<typename ReturnType, typename... Args, typename... Policies>
+ class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const, Policies...) {
+ using namespace internal;
+
+ typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, AllowedRawPointer<const ClassType>, Args...> args;
+ _embind_register_class_function(
+ TypeID<ClassType>::get(),
+ methodName,
+ args.count,
+ args.types,
+ reinterpret_cast<GenericFunction>(&MethodInvoker<decltype(memberFunction), ReturnType, const ClassType*, Args...>::invoke),
+ getContext(memberFunction));
+ return *this;
+ }
+
+ template<typename ReturnType, typename ThisType, typename... Args, typename... Policies>
+ class_& function(const char* methodName, ReturnType (*function)(ThisType, Args...), Policies...) {
+ using namespace internal;
+
+ typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, ThisType, Args...> args;
+ _embind_register_class_function(
+ TypeID<ClassType>::get(),
methodName,
- internal::getTypeID<ReturnType>(),
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(&internal::ConstMethodInvoker<ClassType, ReturnType, Args...>::invoke),
- sizeof(memberFunction),
- &memberFunction);
+ reinterpret_cast<GenericFunction>(&FunctionInvoker<decltype(function), ReturnType, ThisType, Args...>::invoke),
+ getContext(function));
return *this;
}
- template<typename FieldType>
- class_& field(const char* fieldName, FieldType ClassType::*field) {
- internal::_embind_register_class_field(
- internal::getTypeID<ClassType>(),
+ template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
+ class_& property(const char* fieldName, const FieldType ClassType::*field) {
+ using namespace internal;
+
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
fieldName,
- internal::getTypeID<FieldType>(),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::get),
- reinterpret_cast<internal::GenericFunction>(&internal::FieldAccess<ClassType, FieldType>::set),
- sizeof(field),
- &field);
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getContext(field),
+ 0,
+ 0,
+ 0);
return *this;
}
- template<typename ReturnType, typename... Args>
- class_& classmethod(const char* methodName, ReturnType (*classMethod)(Args...)) {
- internal::ArgTypeList<Args...> args;
- internal::_embind_register_class_classmethod(
- internal::getTypeID<ClassType>(),
+ template<typename FieldType, typename = typename std::enable_if<!std::is_function<FieldType>::value>::type>
+ class_& property(const char* fieldName, FieldType ClassType::*field) {
+ using namespace internal;
+
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template getWire<ClassType>),
+ getContext(field),
+ TypeID<FieldType>::get(),
+ reinterpret_cast<GenericFunction>(&MemberAccess<ClassType, FieldType>::template setWire<ClassType>),
+ getContext(field));
+ return *this;
+ }
+
+ template<typename Getter>
+ class_& property(const char* fieldName, Getter getter) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ 0,
+ 0,
+ 0);
+ return *this;
+ }
+
+ template<typename Getter, typename Setter>
+ class_& property(const char* fieldName, Getter getter, Setter setter) {
+ using namespace internal;
+ typedef GetterPolicy<Getter> GP;
+ typedef SetterPolicy<Setter> SP;
+ _embind_register_class_property(
+ TypeID<ClassType>::get(),
+ fieldName,
+ TypeID<typename GP::ReturnType>::get(),
+ reinterpret_cast<GenericFunction>(&GP::template get<ClassType>),
+ GP::getContext(getter),
+ TypeID<typename SP::ArgumentType>::get(),
+ reinterpret_cast<GenericFunction>(&SP::template set<ClassType>),
+ SP::getContext(setter));
+ return *this;
+ }
+
+ template<typename ReturnType, typename... Args, typename... Policies>
+ class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) {
+ using namespace internal;
+
+ typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args;
+ _embind_register_class_class_function(
+ TypeID<ClassType>::get(),
methodName,
- internal::getTypeID<ReturnType>(),
args.count,
args.types,
- reinterpret_cast<internal::GenericFunction>(classMethod));
+ reinterpret_cast<internal::GenericFunction>(&internal::Invoker<ReturnType, Args...>::invoke),
+ reinterpret_cast<GenericFunction>(classMethod));
return *this;
}
};
+ ////////////////////////////////////////////////////////////////////////////////
+ // VECTORS
+ ////////////////////////////////////////////////////////////////////////////////
+
+ namespace internal {
+ template<typename VectorType>
+ struct VectorAccess {
+ static val get(
+ const VectorType& v,
+ typename VectorType::size_type index
+ ) {
+ if (index < v.size()) {
+ return val(v[index]);
+ } else {
+ return val::undefined();
+ }
+ }
+
+ static bool set(
+ VectorType& v,
+ typename VectorType::size_type index,
+ const typename VectorType::value_type& value
+ ) {
+ v[index] = value;
+ return true;
+ }
+ };
+ }
+
+ template<typename T>
+ class_<std::vector<T>> register_vector(const char* name) {
+ typedef std::vector<T> VecType;
+
+ void (VecType::*push_back)(const T&) = &VecType::push_back;
+ return class_<std::vector<T>>(name)
+ .template constructor<>()
+ .function("push_back", push_back)
+ .function("size", &VecType::size)
+ .function("get", &internal::VectorAccess<VecType>::get)
+ .function("set", &internal::VectorAccess<VecType>::set)
+ ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // MAPS
+ ////////////////////////////////////////////////////////////////////////////////
+
+ namespace internal {
+ template<typename MapType>
+ struct MapAccess {
+ static val get(
+ const MapType& m,
+ const typename MapType::key_type& k
+ ) {
+ auto i = m.find(k);
+ if (i == m.end()) {
+ return val::undefined();
+ } else {
+ return val(i->second);
+ }
+ }
+
+ static void set(
+ MapType& m,
+ const typename MapType::key_type& k,
+ const typename MapType::mapped_type& v
+ ) {
+ m[k] = v;
+ }
+ };
+ }
+
+ template<typename K, typename V>
+ class_<std::map<K, V>> register_map(const char* name) {
+ typedef std::map<K,V> MapType;
+
+ return class_<MapType>(name)
+ .template constructor<>()
+ .function("size", &MapType::size)
+ .function("get", internal::MapAccess<MapType>::get)
+ .function("set", internal::MapAccess<MapType>::set)
+ ;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // ENUMS
+ ////////////////////////////////////////////////////////////////////////////////
+
template<typename EnumType>
class enum_ {
public:
enum_(const char* name) {
_embind_register_enum(
- internal::getTypeID<EnumType>(),
+ internal::TypeID<EnumType>::get(),
name);
}
@@ -520,13 +1188,39 @@ namespace emscripten {
static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue");
_embind_register_enum_value(
- internal::getTypeID<EnumType>(),
+ internal::TypeID<EnumType>::get(),
name,
static_cast<internal::GenericEnumValue>(value));
return *this;
}
};
+ ////////////////////////////////////////////////////////////////////////////////
+ // CONSTANTS
+ ////////////////////////////////////////////////////////////////////////////////
+
+ namespace internal {
+ template<typename T>
+ uintptr_t asGenericValue(T t) {
+ return static_cast<uintptr_t>(t);
+ }
+
+ template<typename T>
+ uintptr_t asGenericValue(T* p) {
+ return reinterpret_cast<uintptr_t>(p);
+ }
+ }
+
+ template<typename ConstantType>
+ void constant(const char* name, const ConstantType& v) {
+ using namespace internal;
+ typedef BindingType<const ConstantType&> BT;
+ _embind_register_constant(
+ name,
+ TypeID<const ConstantType&>::get(),
+ asGenericValue(BindingType<const ConstantType&>::toWireType(v)));
+ }
+
namespace internal {
template<typename T>
class optional {
@@ -541,13 +1235,22 @@ namespace emscripten {
}
}
- optional(const optional&) = delete;
+ optional(const optional& rhs)
+ : initialized(false)
+ {
+ *this = rhs;
+ }
T& operator*() {
assert(initialized);
return *get();
}
+ const T& operator*() const {
+ assert(initialized);
+ return *get();
+ }
+
explicit operator bool() const {
return initialized;
}
@@ -560,89 +1263,47 @@ namespace emscripten {
initialized = true;
return *this;
}
-
+
+ optional& operator=(const optional& o) {
+ if (initialized) {
+ get()->~T();
+ }
+ if (o.initialized) {
+ new(get()) T(*o);
+ }
+ initialized = o.initialized;
+ return *this;
+ }
+
private:
T* get() {
return reinterpret_cast<T*>(&data);
}
+ T const* get() const {
+ return reinterpret_cast<T const*>(&data);
+ }
+
bool initialized;
typename std::aligned_storage<sizeof(T)>::type data;
};
}
+}
- template<typename InterfaceType>
- class wrapper : public InterfaceType {
- public:
- // Not necessary in any example so far, but appeases a compiler warning.
- virtual ~wrapper() {}
-
- typedef InterfaceType interface;
-
- void initialize(internal::EM_VAL handle) {
- if (jsobj) {
- internal::_embind_fatal_error(
- "Cannot initialize interface wrapper twice",
- typeid(InterfaceType).name());
- }
- jsobj = val::take_ownership(handle);
- }
-
- template<typename ReturnType, typename... Args>
- ReturnType call(const char* name, Args... args) {
- assertInitialized();
- return Caller<ReturnType, Args...>::call(*jsobj, name, args...);
- }
-
- private:
- // this class only exists because you can't partially specialize function templates
- template<typename ReturnType, typename... Args>
- struct Caller {
- static ReturnType call(val& v, const char* name, Args... args) {
- return v.call(name, args...).template as<ReturnType>();
- }
- };
-
- template<typename... Args>
- struct Caller<void, Args...> {
- static void call(val& v, const char* name, Args... args) {
- v.call(name, args...);
+namespace emscripten {
+ namespace internal {
+ class BindingsDefinition {
+ public:
+ template<typename Function>
+ BindingsDefinition(Function fn) {
+ fn();
}
};
-
- void assertInitialized() {
- if (!jsobj) {
- internal::_embind_fatal_error(
- "Cannot invoke call on uninitialized interface wrapper.",
- typeid(InterfaceType).name());
- }
- }
-
- internal::optional<val> jsobj;
- };
-
- namespace internal {
- template<typename WrapperType>
- WrapperType* create_interface_wrapper(EM_VAL e) {
- WrapperType* p = new WrapperType;
- p->initialize(e);
- return p;
- }
}
-
- template<typename WrapperType>
- class interface {
- public:
- typedef typename WrapperType::interface InterfaceType;
-
- interface(const char* name) {
- _embind_register_interface(
- internal::getTypeID<InterfaceType>(),
- name,
- reinterpret_cast<internal::GenericFunction>(&internal::create_interface_wrapper<WrapperType>),
- reinterpret_cast<internal::GenericFunction>(&internal::raw_destructor<WrapperType>));
- }
- };
}
-#define EMSCRIPTEN_BINDINGS(fn) static emscripten::internal::BindingsDefinition anon_symbol(fn);
+#define EMSCRIPTEN_BINDINGS(name) \
+ static struct BindingInitializer_##name { \
+ BindingInitializer_##name(); \
+ } BindingInitializer_##name##_instance; \
+ BindingInitializer_##name::BindingInitializer_##name()
diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h
index 96db9326..09cad80e 100644
--- a/system/include/emscripten/val.h
+++ b/system/include/emscripten/val.h
@@ -2,58 +2,136 @@
#include <stdint.h> // uintptr_t
#include <emscripten/wire.h>
+#include <vector>
namespace emscripten {
namespace internal {
// Implemented in JavaScript. Don't call these directly.
extern "C" {
+ void _emval_register_symbol(const char*);
+
typedef struct _EM_VAL* EM_VAL;
void _emval_incref(EM_VAL value);
void _emval_decref(EM_VAL value);
+
+ EM_VAL _emval_new_array();
EM_VAL _emval_new_object();
- EM_VAL _emval_new_long(long value);
- EM_VAL _emval_new_cstring(const char* str);
- EM_VAL _emval_get_property(EM_VAL object, const char* key);
- EM_VAL _emval_get_property_by_long(EM_VAL object, long key);
- EM_VAL _emval_get_property_by_unsigned_long(EM_VAL object, unsigned long key);
- void _emval_set_property(EM_VAL object, const char* key, EM_VAL value);
- void _emval_set_property_by_int(EM_VAL object, long key, EM_VAL value);
- void _emval_as(EM_VAL value, emscripten::internal::TypeID returnType);
+ EM_VAL _emval_undefined();
+ EM_VAL _emval_null();
+ EM_VAL _emval_new_cstring(const char*);
+ void _emval_take_value(TYPEID type/*, ...*/);
+
+ EM_VAL _emval_new(
+ EM_VAL value,
+ unsigned argCount,
+ internal::TYPEID argTypes[]
+ /*, ... */);
+
+ EM_VAL _emval_get_global(const char* name);
+ EM_VAL _emval_get_module_property(const char* name);
+ EM_VAL _emval_get_property(EM_VAL object, EM_VAL key);
+ void _emval_set_property(EM_VAL object, EM_VAL key, EM_VAL value);
+ void _emval_as(EM_VAL value, TYPEID returnType);
EM_VAL _emval_call(
EM_VAL value,
unsigned argCount,
- internal::TypeID argTypes[]
+ internal::TYPEID argTypes[]
/*, ... */);
EM_VAL _emval_call_method(
EM_VAL value,
const char* methodName,
unsigned argCount,
- internal::TypeID argTypes[]
+ internal::TYPEID argTypes[]
/*, ... */);
+ void _emval_call_void_method(
+ EM_VAL value,
+ const char* methodName,
+ unsigned argCount,
+ internal::TYPEID argTypes[]
+ /*, ...*/);
+ bool _emval_has_function(
+ EM_VAL value,
+ const char* methodName);
}
}
+ template<const char* address>
+ struct symbol_registrar {
+ symbol_registrar() {
+ internal::_emval_register_symbol(address);
+ }
+ };
+
+#define EMSCRIPTEN_SYMBOL(name) \
+ static const char name##_symbol[] = #name; \
+ static const symbol_registrar<name##_symbol> name##_registrar
+
class val {
public:
+ // missing operators:
+ // * delete
+ // * in
+ // * instanceof
+ // * typeof
+ // * ! ~ - + ++ --
+ // * * / %
+ // * + -
+ // * << >> >>>
+ // * < <= > >=
+ // * == != === !==
+ // * & ^ | && || ?:
+ //
+ // exposing void, comma, and conditional is unnecessary
+ // same with: = += -= *= /= %= <<= >>= >>>= &= ^= |=
+
+ static val array() {
+ return val(internal::_emval_new_array());
+ }
+
static val object() {
return val(internal::_emval_new_object());
- };
+ }
+
+ static val undefined() {
+ return val(internal::_emval_undefined());
+ }
+
+ static val null() {
+ return val(internal::_emval_null());
+ }
static val take_ownership(internal::EM_VAL e) {
return val(e);
}
- explicit val(long l)
- : handle(internal::_emval_new_long(l))
- {}
+ static val global(const char* name) {
+ return val(internal::_emval_get_global(name));
+ }
- explicit val(const char* str)
- : handle(internal::_emval_new_cstring(str))
- {}
+ static val module_property(const char* name) {
+ return val(internal::_emval_get_module_property(name));
+ }
+
+ template<typename T>
+ explicit val(T&& value) {
+ typedef internal::BindingType<T> BT;
+ auto taker = reinterpret_cast<internal::EM_VAL (*)(internal::TYPEID, typename BT::WireType)>(&internal::_emval_take_value);
+ handle = taker(internal::TypeID<T>::get(), BT::toWireType(std::forward<T>(value)));
+ }
val() = delete;
+ explicit val(const char* v)
+ : handle(internal::_emval_new_cstring(v))
+ {}
+
+ val(val&& v)
+ : handle(v.handle)
+ {
+ v.handle = 0;
+ }
+
val(const val& v)
: handle(v.handle)
{
@@ -64,89 +142,132 @@ namespace emscripten {
internal::_emval_decref(handle);
}
- val& operator=(const val& v) {
- internal::_emval_incref(v.handle);
+ val& operator=(val&& v) {
internal::_emval_decref(handle);
handle = v.handle;
+ v.handle = 0;
return *this;
}
- val get(const char* key) const {
- return val(internal::_emval_get_property(handle, key));
+ val& operator=(const val& v) {
+ internal::_emval_incref(v.handle);
+ internal::_emval_decref(handle);
+ handle = v.handle;
+ return *this;
}
- val get(int key) const {
- return get(long(key));
+ bool hasOwnProperty(const char* key) const {
+ return val::global("Object")["prototype"]["hasOwnProperty"].call("call", *this, val(key)).as<bool>();
}
- val get(unsigned int key) const {
- typedef unsigned long T;
- return get(T(key));
- }
+ template<typename... Args>
+ val new_(Args&&... args) const {
+ using namespace internal;
- val get(long key) const {
- return val(internal::_emval_get_property_by_long(handle, key));
+ WithPolicies<>::ArgTypeList<Args...> argList;
+ // todo: this is awfully similar to operator(), can we
+ // merge them somehow?
+ typedef EM_VAL (*TypedNew)(
+ EM_VAL,
+ unsigned,
+ TYPEID argTypes[],
+ typename BindingType<Args>::WireType...);
+ TypedNew typedNew = reinterpret_cast<TypedNew>(&_emval_new);
+ return val(
+ typedNew(
+ handle,
+ argList.count,
+ argList.types,
+ toWireType(std::forward<Args>(args))...));
}
-
- val get(unsigned long key) const {
- return val(internal::_emval_get_property_by_unsigned_long(handle, key));
+
+ template<typename T>
+ val operator[](const T& key) const {
+ return val(internal::_emval_get_property(handle, val(key).handle));
}
- void set(const char* key, val v) {
- internal::_emval_set_property(handle, key, v.handle);
+ template<typename T>
+ void set(const T& key, val v) {
+ internal::_emval_set_property(handle, val(key).handle, v.handle);
}
- void set(long key, val v) {
- internal::_emval_set_property_by_int(handle, key, v.handle);
- }
+ template<typename... Args>
+ val operator()(Args&&... args) {
+ using namespace internal;
- template<typename ...Args>
- val operator()(Args... args) {
- internal::ArgTypeList<Args...> argList;
- typedef internal::EM_VAL (*TypedCall)(
- internal::EM_VAL,
+ WithPolicies<>::ArgTypeList<Args...> argList;
+ typedef EM_VAL (*TypedCall)(
+ EM_VAL,
unsigned,
- internal::TypeID argTypes[],
- typename internal::BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&internal::_emval_call);
+ TYPEID argTypes[],
+ typename BindingType<Args>::WireType...);
+ TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call);
return val(
typedCall(
handle,
argList.count,
argList.types,
- internal::toWireType(args)...));
+ toWireType(std::forward<Args>(args))...));
}
template<typename ...Args>
- val call(const char* name, Args... args) {
- internal::ArgTypeList<Args...> argList;
- typedef internal::EM_VAL (*TypedCall)(
- internal::EM_VAL,
+ val call(const char* name, Args&&... args) const {
+ using namespace internal;
+
+ WithPolicies<>::ArgTypeList<Args...> argList;
+ typedef EM_VAL (*TypedCall)(
+ EM_VAL,
const char* name,
unsigned,
- internal::TypeID argTypes[],
- typename internal::BindingType<Args>::WireType...);
- TypedCall typedCall = reinterpret_cast<TypedCall>(&internal::_emval_call_method);
+ TYPEID argTypes[],
+ typename BindingType<Args>::WireType...);
+ TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_method);
return val(
typedCall(
handle,
name,
argList.count,
argList.types,
- internal::toWireType(args)...));
+ toWireType(std::forward<Args>(args))...));
+ }
+
+ template<typename ...Args>
+ void call_void(const char* name, Args&&... args) const {
+ using namespace internal;
+
+ WithPolicies<>::ArgTypeList<Args...> argList;
+ typedef void (*TypedCall)(
+ EM_VAL,
+ const char* name,
+ unsigned,
+ TYPEID argTypes[],
+ typename BindingType<Args>::WireType...);
+ TypedCall typedCall = reinterpret_cast<TypedCall>(&_emval_call_void_method);
+ return typedCall(
+ handle,
+ name,
+ argList.count,
+ argList.types,
+ toWireType(std::forward<Args>(args))...);
+ }
+
+ bool has_function(const char* name) const {
+ return _emval_has_function(handle, name);
}
template<typename T>
T as() const {
- typedef internal::BindingType<T> BT;
+ using namespace internal;
+
+ typedef BindingType<T> BT;
typedef typename BT::WireType (*TypedAs)(
- internal::EM_VAL value,
- emscripten::internal::TypeID returnType);
- TypedAs typedAs = reinterpret_cast<TypedAs>(&internal::_emval_as);
+ EM_VAL value,
+ TYPEID returnType);
+ TypedAs typedAs = reinterpret_cast<TypedAs>(&_emval_as);
- typename BT::WireType wt = typedAs(handle, internal::getTypeID<T>());
- internal::WireDeleter<T> deleter(wt);
+ typename BT::WireType wt = typedAs(handle, TypeID<T>::get());
+ WireDeleter<T> deleter(wt);
return BT::fromWireType(wt);
}
@@ -165,13 +286,27 @@ namespace emscripten {
template<>
struct BindingType<val> {
typedef internal::EM_VAL WireType;
- static WireType toWireType(val v) {
+ static WireType toWireType(const val& v) {
_emval_incref(v.handle);
return v.handle;
}
static val fromWireType(WireType v) {
- return val(v);
+ return val::take_ownership(v);
+ }
+ static void destroy(WireType v) {
}
};
}
+
+ template<typename T>
+ std::vector<T> vecFromJSArray(val v) {
+ auto l = v["length"].as<unsigned>();
+
+ std::vector<T> rv;
+ for(unsigned i = 0; i < l; ++i) {
+ rv.push_back(v[i].as<T>());
+ }
+
+ return rv;
+ };
}
diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h
index fbf0897d..6fb15fc7 100644..100755
--- a/system/include/emscripten/wire.h
+++ b/system/include/emscripten/wire.h
@@ -7,66 +7,110 @@
//
// We'll call the on-the-wire type WireType.
+#include <cstdlib>
+#include <memory>
+#include <string>
+
namespace emscripten {
namespace internal {
- typedef const struct _TypeID* TypeID;
+ typedef const struct _TYPEID* TYPEID;
// This implementation is technically not legal, as it's not
// required that two calls to typeid produce the same exact
- // std::type_info instance. That said, it's likely to work.
- // Should it not work in the future: replace TypeID with
- // an int, and store all TypeInfo we see in a map, allocating
- // new TypeIDs as we add new items to the map.
+ // std::type_info instance. That said, it's likely to work
+ // given Emscripten compiles everything into one binary.
+ // Should it not work in the future: replace TypeID with an
+ // int, and store all TypeInfo we see in a map, allocating new
+ // TypeIDs as we add new items to the map.
template<typename T>
- inline TypeID getTypeID() {
- return reinterpret_cast<TypeID>(&typeid(T));
- }
+ struct TypeID {
+ static TYPEID get() {
+ return reinterpret_cast<TYPEID>(&typeid(T));
+ }
+ };
- // count<>
+ template<typename T>
+ struct TypeID<std::unique_ptr<T>> {
+ static TYPEID get() {
+ return TypeID<T>::get();
+ }
+ };
- template<typename... Args>
- struct count;
+ template<typename T>
+ struct TypeID<T*> {
+ static_assert(!std::is_pointer<T*>::value, "Implicitly binding raw pointers is illegal. Specify allow_raw_pointer<arg<?>>");
+ };
- template<>
- struct count<> {
- enum { value = 0 };
+ template<typename T>
+ struct AllowedRawPointer {
};
- template<typename T, typename... Args>
- struct count<T, Args...> {
- enum { value = 1 + count<Args...>::value };
+ template<typename T>
+ struct TypeID<AllowedRawPointer<T>> {
+ static TYPEID get() {
+ return reinterpret_cast<TYPEID>(&typeid(T*));
+ }
};
+
+ // ExecutePolicies<>
- // ArgTypeList<>
+ template<typename... Policies>
+ struct ExecutePolicies;
- template<typename... Args>
+ template<>
+ struct ExecutePolicies<> {
+ template<typename T, int Index>
+ struct With {
+ typedef T type;
+ };
+ };
+
+ template<typename Policy, typename... Remaining>
+ struct ExecutePolicies<Policy, Remaining...> {
+ template<typename T, int Index>
+ struct With {
+ typedef typename Policy::template Transform<
+ typename ExecutePolicies<Remaining...>::template With<T, Index>::type,
+ Index
+ >::type type;
+ };
+ };
+
+ // ArgTypes<>
+
+ template<int Index, typename... Args>
struct ArgTypes;
- template<>
- struct ArgTypes<> {
- static void fill(TypeID* argTypes) {
+ template<int Index>
+ struct ArgTypes<Index> {
+ template<typename... Policies>
+ static void fill(TYPEID* argTypes) {
}
};
- template<typename T, typename... Args>
- struct ArgTypes<T, Args...> {
- static void fill(TypeID* argTypes) {
- *argTypes = getTypeID<T>();
- return ArgTypes<Args...>::fill(argTypes + 1);
+ template<int Index, typename T, typename... Remaining>
+ struct ArgTypes<Index, T, Remaining...> {
+ template<typename... Policies>
+ static void fill(TYPEID* argTypes) {
+ typedef typename ExecutePolicies<Policies...>::template With<T, Index>::type TransformT;
+ *argTypes = TypeID<TransformT>::get();
+ return ArgTypes<Index + 1, Remaining...>::template fill<Policies...>(argTypes + 1);
}
};
- template<typename... Args>
- struct ArgTypeList {
- enum { args_count = count<Args...>::value };
-
- ArgTypeList() {
- count = args_count;
- ArgTypes<Args...>::fill(types);
- }
+ // WithPolicies<...>::ArgTypeList<...>
+ template<typename... Policies>
+ struct WithPolicies {
+ template<typename... Args>
+ struct ArgTypeList {
+ ArgTypeList() {
+ count = sizeof...(Args);
+ ArgTypes<0, Args...>::template fill<Policies...>(types);
+ }
- unsigned count;
- TypeID types[args_count];
+ unsigned count;
+ TYPEID types[sizeof...(Args)];
+ };
};
// BindingType<T>
@@ -74,19 +118,18 @@ namespace emscripten {
template<typename T>
struct BindingType;
-#define EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(type) \
- template<> \
- struct BindingType<type> { \
- typedef type WireType; \
- \
- constexpr static WireType toWireType(type v) { \
- return v; \
- } \
- constexpr static type fromWireType(WireType v) { \
- return v; \
- } \
- static void destroy(WireType) { \
- } \
+#define EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(type) \
+ template<> \
+ struct BindingType<type> { \
+ typedef type WireType; \
+ constexpr static WireType toWireType(const type& v) { \
+ return v; \
+ } \
+ constexpr static type fromWireType(WireType v) { \
+ return v; \
+ } \
+ static void destroy(WireType) { \
+ } \
}
EMSCRIPTEN_DEFINE_NATIVE_BINDING_TYPE(char);
@@ -120,35 +163,75 @@ namespace emscripten {
template<>
struct BindingType<std::string> {
- typedef char* WireType;
- static WireType toWireType(std::string v) {
- return strdup(v.c_str());
+ typedef struct {
+ size_t length;
+ char data[1]; // trailing data
+ }* WireType;
+ static WireType toWireType(const std::string& v) {
+ WireType wt = (WireType)malloc(sizeof(size_t) + v.length());
+ wt->length = v.length();
+ memcpy(wt->data, v.data(), v.length());
+ return wt;
+ }
+ static std::string fromWireType(WireType v) {
+ return std::string(v->data, v->length);
}
- static std::string fromWireType(char* v) {
- return std::string(v);
+ static void destroy(WireType v) {
+ free(v);
}
};
template<>
- struct BindingType<const std::string&> {
- typedef char* WireType;
- static WireType toWireType(std::string v) {
- return strdup(v.c_str());
+ struct BindingType<std::wstring> {
+ typedef struct {
+ size_t length;
+ wchar_t data[1]; // trailing data
+ }* WireType;
+ static WireType toWireType(const std::wstring& v) {
+ WireType wt = (WireType)malloc(sizeof(size_t) + v.length() * sizeof(wchar_t));
+ wt->length = v.length();
+ wmemcpy(wt->data, v.data(), v.length());
+ return wt;
+ }
+ static std::wstring fromWireType(WireType v) {
+ return std::wstring(v->data, v->length);
}
- static std::string fromWireType(char* v) {
- return std::string(v);
+ static void destroy(WireType v) {
+ free(v);
}
};
- template<typename Enum>
- struct EnumBindingType {
- typedef Enum WireType;
+ template<typename T>
+ struct BindingType<const T> : public BindingType<T> {
+ };
- static WireType toWireType(Enum v) {
- return v;
+ template<typename T>
+ struct BindingType<T&> : public BindingType<T> {
+ };
+
+ template<typename T>
+ struct BindingType<const T&> : public BindingType<T> {
+ };
+
+ template<typename T>
+ struct BindingType<T&&> {
+ typedef typename BindingType<T>::WireType WireType;
+ static WireType toWireType(const T& v) {
+ return BindingType<T>::toWireType(v);
}
- static Enum fromWireType(WireType v) {
- return v;
+ static T fromWireType(WireType wt) {
+ return BindingType<T>::fromWireType(wt);
+ }
+ };
+
+ template<typename T>
+ struct BindingType<T*> {
+ typedef T* WireType;
+ static WireType toWireType(T* p) {
+ return p;
+ }
+ static T* fromWireType(WireType wt) {
+ return wt;
}
};
@@ -157,33 +240,16 @@ namespace emscripten {
typedef typename std::remove_reference<T>::type ActualT;
typedef ActualT* WireType;
- struct Marshaller {
- explicit Marshaller(WireType wt)
- : wireType(wt)
- {}
-
- Marshaller(Marshaller&& wt)
- : wireType(wt.wireType)
- {
- wt.wireType = 0;
- }
-
- operator ActualT&() const {
- return *wireType;
- }
-
- private:
- Marshaller() = delete;
- Marshaller(const Marshaller&) = delete;
- ActualT* wireType;
- };
-
- static WireType toWireType(T v) {
+ static WireType toWireType(const T& v) {
return new T(v);
}
- static Marshaller fromWireType(WireType p) {
- return Marshaller(p);
+ static WireType toWireType(T&& v) {
+ return new T(std::forward<T>(v));
+ }
+
+ static ActualT& fromWireType(WireType p) {
+ return *p;
}
static void destroy(WireType p) {
@@ -191,19 +257,28 @@ namespace emscripten {
}
};
+ // Is this necessary?
template<typename T>
- struct WireDeleter {
+ struct GenericBindingType<std::unique_ptr<T>> {
typedef typename BindingType<T>::WireType WireType;
-
- WireDeleter(WireType wt)
- : wt(wt)
- {}
-
- ~WireDeleter() {
- BindingType<T>::destroy(wt);
+
+ static WireType toWireType(std::unique_ptr<T> p) {
+ return BindingType<T>::toWireType(*p);
+ }
+ };
+
+ template<typename Enum>
+ struct EnumBindingType {
+ typedef Enum WireType;
+
+ static WireType toWireType(Enum v) {
+ return v;
+ }
+ static Enum fromWireType(WireType v) {
+ return v;
+ }
+ static void destroy(WireType) {
}
-
- WireType wt;
};
// catch-all generic binding
@@ -215,9 +290,23 @@ namespace emscripten {
{};
template<typename T>
- auto toWireType(const T& v) -> typename BindingType<T>::WireType {
- return BindingType<T>::toWireType(v);
+ auto toWireType(T&& v) -> typename BindingType<T>::WireType {
+ return BindingType<T>::toWireType(std::forward<T>(v));
}
+ template<typename T>
+ struct WireDeleter {
+ typedef typename BindingType<T>::WireType WireType;
+
+ WireDeleter(WireType wt)
+ : wt(wt)
+ {}
+
+ ~WireDeleter() {
+ BindingType<T>::destroy(wt);
+ }
+
+ WireType wt;
+ };
}
}
diff --git a/system/lib/compiler-rt/LICENSE.TXT b/system/lib/compiler-rt/LICENSE.TXT
new file mode 100644
index 00000000..6aab1f69
--- /dev/null
+++ b/system/lib/compiler-rt/LICENSE.TXT
@@ -0,0 +1,97 @@
+==============================================================================
+compiler_rt License
+==============================================================================
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties. Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program Directory
+------- ---------
+mach_override lib/interception/mach_override
diff --git a/system/lib/compiler-rt/divdi3.c b/system/lib/compiler-rt/divdi3.c
new file mode 100644
index 00000000..09f4a04e
--- /dev/null
+++ b/system/lib/compiler-rt/divdi3.c
@@ -0,0 +1,47 @@
+/* ===-- divdi3.c - Implement __divdi3 -------------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __divdi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
+
+/* Returns: a / b */
+
+COMPILER_RT_ABI di_int
+__divdi3(di_int a, di_int b)
+{
+ const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+ di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */
+ di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */
+ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */
+ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
+ s_a ^= s_b; /*sign of quotient */
+ return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
+}
+
+/* XXX EMSCRIPTEN */
+
+COMPILER_RT_ABI di_int
+__remdi3(di_int a, di_int b)
+{
+ const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
+ di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */
+ di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */
+ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */
+ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
+ du_int rem;
+ __udivmoddi4(a, b, &rem);
+ return (rem ^ s_a) - s_a; /* negate if s_a == -1 */
+}
+
diff --git a/system/lib/compiler-rt/int_endianness.h b/system/lib/compiler-rt/int_endianness.h
new file mode 100644
index 00000000..17905355
--- /dev/null
+++ b/system/lib/compiler-rt/int_endianness.h
@@ -0,0 +1,116 @@
+/* ===-- int_endianness.h - configuration header for compiler-rt ------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is a configuration header for compiler-rt.
+ * This file is not part of the interface of this library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_ENDIANNESS_H
+#define INT_ENDIANNESS_H
+
+#if defined(__SVR4) && defined(__sun)
+#include <sys/byteorder.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* Solaris and AuroraUX. */
+
+/* .. */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__minix)
+#include <sys/endian.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* *BSD */
+
+#if defined(__OpenBSD__) || defined(__Bitrig__)
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* _BYTE_ORDER */
+
+#endif /* OpenBSD and Bitrig. */
+
+/* .. */
+
+/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the compiler (at least with GCC) */
+#if defined(__APPLE__) && defined(__MACH__) || defined(__ellcc__ )
+
+#ifdef __BIG_ENDIAN__
+#if __BIG_ENDIAN__
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#endif
+#endif /* __BIG_ENDIAN__ */
+
+#ifdef __LITTLE_ENDIAN__
+#if __LITTLE_ENDIAN__
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif
+#endif /* __LITTLE_ENDIAN__ */
+
+#endif /* Mac OSX */
+
+/* .. */
+
+#if defined(__linux__)
+#include <endian.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 0
+#define _YUGA_BIG_ENDIAN 1
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+#endif /* __BYTE_ORDER */
+
+#endif /* GNU/Linux */
+
+#if defined(_WIN32)
+
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+
+#endif /* Windows */
+
+#if defined(EMSCRIPTEN)
+
+#define _YUGA_LITTLE_ENDIAN 1
+#define _YUGA_BIG_ENDIAN 0
+
+#endif /* emscripten */
+
+/* . */
+
+#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN)
+#error Unable to determine endian
+#endif /* Check we found an endianness correctly. */
+
+#endif /* INT_ENDIANNESS_H */
diff --git a/system/lib/compiler-rt/int_lib.h b/system/lib/compiler-rt/int_lib.h
new file mode 100644
index 00000000..a87426c5
--- /dev/null
+++ b/system/lib/compiler-rt/int_lib.h
@@ -0,0 +1,46 @@
+/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is a configuration header for compiler-rt.
+ * This file is not part of the interface of this library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_LIB_H
+#define INT_LIB_H
+
+/* Assumption: Signed integral is 2's complement. */
+/* Assumption: Right shift of signed negative is arithmetic shift. */
+/* Assumption: Endianness is little or big (not mixed). */
+
+/* ABI macro definitions */
+
+#if __ARM_EABI__
+# define ARM_EABI_FNALIAS(aeabi_name, name) \
+ void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
+# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+#else
+# define ARM_EABI_FNALIAS(aeabi_name, name)
+# define COMPILER_RT_ABI
+#endif
+
+/* Include the standard compiler builtin headers we use functionality from. */
+#include <limits.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <float.h>
+
+/* Include the commonly used internal type definitions. */
+#include "int_types.h"
+
+/* Include internal utility function declarations. */
+#include "int_util.h"
+
+#endif /* INT_LIB_H */
diff --git a/system/lib/compiler-rt/int_math.h b/system/lib/compiler-rt/int_math.h
new file mode 100644
index 00000000..d6b4bdae
--- /dev/null
+++ b/system/lib/compiler-rt/int_math.h
@@ -0,0 +1,67 @@
+/* ===-- int_math.h - internal math inlines ---------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===-----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines substitutes for the libm functions used in some of the
+ * compiler-rt implementations, defined in such a way that there is not a direct
+ * dependency on libm or math.h. Instead, we use the compiler builtin versions
+ * where available. This reduces our dependencies on the system SDK by foisting
+ * the responsibility onto the compiler.
+ *
+ * ===-----------------------------------------------------------------------===
+ */
+
+#ifndef INT_MATH_H
+#define INT_MATH_H
+
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+#define CRT_INFINITY __builtin_huge_valf()
+
+#define crt_isinf(x) __builtin_isinf((x))
+#define crt_isnan(x) __builtin_isnan((x))
+
+/* Define crt_isfinite in terms of the builtin if available, otherwise provide
+ * an alternate version in terms of our other functions. This supports some
+ * versions of GCC which didn't have __builtin_isfinite.
+ */
+#if __has_builtin(__builtin_isfinite)
+# define crt_isfinite(x) __builtin_isfinite((x))
+#else
+# define crt_isfinite(x) \
+ __extension__(({ \
+ __typeof((x)) x_ = (x); \
+ !crt_isinf(x_) && !crt_isnan(x_); \
+ }))
+#endif
+
+#define crt_copysign(x, y) __builtin_copysign((x), (y))
+#define crt_copysignf(x, y) __builtin_copysignf((x), (y))
+#define crt_copysignl(x, y) __builtin_copysignl((x), (y))
+
+#define crt_fabs(x) __builtin_fabs((x))
+#define crt_fabsf(x) __builtin_fabsf((x))
+#define crt_fabsl(x) __builtin_fabsl((x))
+
+#define crt_fmax(x, y) __builtin_fmax((x), (y))
+#define crt_fmaxf(x, y) __builtin_fmaxf((x), (y))
+#define crt_fmaxl(x, y) __builtin_fmaxl((x), (y))
+
+#define crt_logb(x) __builtin_logb((x))
+#define crt_logbf(x) __builtin_logbf((x))
+#define crt_logbl(x) __builtin_logbl((x))
+
+#define crt_scalbn(x, y) __builtin_scalbn((x), (y))
+#define crt_scalbnf(x, y) __builtin_scalbnf((x), (y))
+#define crt_scalbnl(x, y) __builtin_scalbnl((x), (y))
+
+#endif /* INT_MATH_H */
diff --git a/system/lib/compiler-rt/int_types.h b/system/lib/compiler-rt/int_types.h
new file mode 100644
index 00000000..fcce390f
--- /dev/null
+++ b/system/lib/compiler-rt/int_types.h
@@ -0,0 +1,140 @@
+/* ===-- int_lib.h - configuration header for compiler-rt -----------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines various standard types, most importantly a number of unions
+ * used to access parts of larger types.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#ifndef INT_TYPES_H
+#define INT_TYPES_H
+
+#include "int_endianness.h"
+
+typedef int si_int;
+typedef unsigned su_int;
+
+typedef long long di_int;
+typedef unsigned long long du_int;
+
+typedef union
+{
+ di_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ su_int low;
+ si_int high;
+#else
+ si_int high;
+ su_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} dwords;
+
+typedef union
+{
+ du_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ su_int low;
+ su_int high;
+#else
+ su_int high;
+ su_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} udwords;
+
+#if __x86_64
+
+typedef int ti_int __attribute__ ((mode (TI)));
+typedef unsigned tu_int __attribute__ ((mode (TI)));
+
+typedef union
+{
+ ti_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ du_int low;
+ di_int high;
+#else
+ di_int high;
+ du_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} twords;
+
+typedef union
+{
+ tu_int all;
+ struct
+ {
+#if _YUGA_LITTLE_ENDIAN
+ du_int low;
+ du_int high;
+#else
+ du_int high;
+ du_int low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+ }s;
+} utwords;
+
+static inline ti_int make_ti(di_int h, di_int l) {
+ twords r;
+ r.s.high = h;
+ r.s.low = l;
+ return r.all;
+}
+
+static inline tu_int make_tu(du_int h, du_int l) {
+ utwords r;
+ r.s.high = h;
+ r.s.low = l;
+ return r.all;
+}
+
+#endif /* __x86_64 */
+
+typedef union
+{
+ su_int u;
+ float f;
+} float_bits;
+
+typedef union
+{
+ udwords u;
+ double f;
+} double_bits;
+
+typedef struct
+{
+#if _YUGA_LITTLE_ENDIAN
+ udwords low;
+ udwords high;
+#else
+ udwords high;
+ udwords low;
+#endif /* _YUGA_LITTLE_ENDIAN */
+} uqwords;
+
+typedef union
+{
+ uqwords u;
+ long double f;
+} long_double_bits;
+
+#endif /* INT_TYPES_H */
+
diff --git a/system/lib/compiler-rt/int_util.h b/system/lib/compiler-rt/int_util.h
new file mode 100644
index 00000000..1348b85e
--- /dev/null
+++ b/system/lib/compiler-rt/int_util.h
@@ -0,0 +1,29 @@
+/* ===-- int_util.h - internal utility functions ----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===-----------------------------------------------------------------------===
+ *
+ * This file is not part of the interface of this library.
+ *
+ * This file defines non-inline utilities which are available for use in the
+ * library. The function definitions themselves are all contained in int_util.c
+ * which will always be compiled into any compiler-rt library.
+ *
+ * ===-----------------------------------------------------------------------===
+ */
+
+#ifndef INT_UTIL_H
+#define INT_UTIL_H
+
+/** \brief Trigger a program abort (or panic for kernel code). */
+#define compilerrt_abort() compilerrt_abort_impl(__FILE__, __LINE__, \
+ __FUNCTION__)
+
+void compilerrt_abort_impl(const char *file, int line,
+ const char *function) __attribute__((noreturn));
+
+#endif /* INT_UTIL_H */
diff --git a/system/lib/compiler-rt/muldi3.c b/system/lib/compiler-rt/muldi3.c
new file mode 100644
index 00000000..2dae44c1
--- /dev/null
+++ b/system/lib/compiler-rt/muldi3.c
@@ -0,0 +1,56 @@
+/* ===-- muldi3.c - Implement __muldi3 -------------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __muldi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Returns: a * b */
+
+static
+di_int
+__muldsi3(su_int a, su_int b)
+{
+ dwords r;
+ const int bits_in_word_2 = (int)(sizeof(si_int) * CHAR_BIT) / 2;
+ const su_int lower_mask = (su_int)~0 >> bits_in_word_2;
+ r.s.low = (a & lower_mask) * (b & lower_mask);
+ su_int t = r.s.low >> bits_in_word_2;
+ r.s.low &= lower_mask;
+ t += (a >> bits_in_word_2) * (b & lower_mask);
+ r.s.low += (t & lower_mask) << bits_in_word_2;
+ r.s.high = t >> bits_in_word_2;
+ t = r.s.low >> bits_in_word_2;
+ r.s.low &= lower_mask;
+ t += (b >> bits_in_word_2) * (a & lower_mask);
+ r.s.low += (t & lower_mask) << bits_in_word_2;
+ r.s.high += t >> bits_in_word_2;
+ r.s.high += (a >> bits_in_word_2) * (b >> bits_in_word_2);
+ return r.all;
+}
+
+/* Returns: a * b */
+
+ARM_EABI_FNALIAS(lmul, muldi3)
+
+COMPILER_RT_ABI di_int
+__muldi3(di_int a, di_int b)
+{
+ dwords x;
+ x.all = a;
+ dwords y;
+ y.all = b;
+ dwords r;
+ r.all = __muldsi3(x.s.low, y.s.low);
+ r.s.high += x.s.high * y.s.low + x.s.low * y.s.high;
+ return r.all;
+}
diff --git a/system/lib/compiler-rt/readme.txt b/system/lib/compiler-rt/readme.txt
new file mode 100644
index 00000000..d10f53e4
--- /dev/null
+++ b/system/lib/compiler-rt/readme.txt
@@ -0,0 +1,20 @@
+These files are from compiler-rt,
+
+Last Changed Rev: 179380
+Last Changed Date: 2013-04-12 07:57:03 -0700 (Fri, 12 Apr 2013)
+
+===========================================================================
+
+Changes:
+
+ * add emscripten endianness to int_endianness.h
+ * add rem functions
+
+===========================================================================
+
+Compile with something like
+
+./emcc system/lib/compiler-rt/*.c -Isystem/lib/compiler-rt/ -o rt.bc
+./emcc -O2 -s ASM_JS=1 -g rt.bc -s LINKABLE=1
+manually replace Math_imul with Math.imul
+
diff --git a/system/lib/compiler-rt/udivdi3.c b/system/lib/compiler-rt/udivdi3.c
new file mode 100644
index 00000000..3d55785c
--- /dev/null
+++ b/system/lib/compiler-rt/udivdi3.c
@@ -0,0 +1,36 @@
+/* ===-- udivdi3.c - Implement __udivdi3 -----------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __udivdi3 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
+
+/* Returns: a / b */
+
+COMPILER_RT_ABI du_int
+__udivdi3(du_int a, du_int b)
+{
+ return __udivmoddi4(a, b, 0);
+}
+
+/* XXX EMSCRIPTEN */
+
+COMPILER_RT_ABI du_int
+__uremdi3(du_int a, du_int b)
+{
+ du_int rem;
+ __udivmoddi4(a, b, &rem);
+ return rem;
+}
+
diff --git a/system/lib/compiler-rt/udivmoddi4.c b/system/lib/compiler-rt/udivmoddi4.c
new file mode 100644
index 00000000..57282d5b
--- /dev/null
+++ b/system/lib/compiler-rt/udivmoddi4.c
@@ -0,0 +1,251 @@
+/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __udivmoddi4 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#include "int_lib.h"
+
+/* Effects: if rem != 0, *rem = a % b
+ * Returns: a / b
+ */
+
+/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
+
+COMPILER_RT_ABI du_int
+__udivmoddi4(du_int a, du_int b, du_int* rem)
+{
+ const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
+ const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
+ udwords n;
+ n.all = a;
+ udwords d;
+ d.all = b;
+ udwords q;
+ udwords r;
+ unsigned sr;
+ /* special cases, X is unknown, K != 0 */
+ if (n.s.high == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* 0 X
+ * ---
+ * 0 X
+ */
+ if (rem)
+ *rem = n.s.low % d.s.low;
+ return n.s.low / d.s.low;
+ }
+ /* 0 X
+ * ---
+ * K X
+ */
+ if (rem)
+ *rem = n.s.low;
+ return 0;
+ }
+ /* n.s.high != 0 */
+ if (d.s.low == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 0
+ */
+ if (rem)
+ *rem = n.s.high % d.s.low;
+ return n.s.high / d.s.low;
+ }
+ /* d.s.high != 0 */
+ if (n.s.low == 0)
+ {
+ /* K 0
+ * ---
+ * K 0
+ */
+ if (rem)
+ {
+ r.s.high = n.s.high % d.s.high;
+ r.s.low = 0;
+ *rem = r.all;
+ }
+ return n.s.high / d.s.high;
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ {
+ r.s.low = n.s.low;
+ r.s.high = n.s.high & (d.s.high - 1);
+ *rem = r.all;
+ }
+ return n.s.high >> __builtin_ctz(d.s.high);
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+ /* 0 <= sr <= n_uword_bits - 2 or sr large */
+ if (sr > n_uword_bits - 2)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_uword_bits - 1 */
+ /* q.all = n.all << (n_udword_bits - sr); */
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_uword_bits - sr);
+ /* r.all = n.all >> sr; */
+ r.s.high = n.s.high >> sr;
+ r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ }
+ else /* d.s.low != 0 */
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 K
+ */
+ if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ *rem = n.s.low & (d.s.low - 1);
+ if (d.s.low == 1)
+ return n.all;
+ sr = __builtin_ctz(d.s.low);
+ q.s.high = n.s.high >> sr;
+ q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ return q.all;
+ }
+ /* K X
+ * ---
+ *0 K
+ */
+ sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
+ /* 2 <= sr <= n_udword_bits - 1
+ * q.all = n.all << (n_udword_bits - sr);
+ * r.all = n.all >> sr;
+ * if (sr == n_uword_bits)
+ * {
+ * q.s.low = 0;
+ * q.s.high = n.s.low;
+ * r.s.high = 0;
+ * r.s.low = n.s.high;
+ * }
+ * else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1
+ * {
+ * q.s.low = 0;
+ * q.s.high = n.s.low << (n_uword_bits - sr);
+ * r.s.high = n.s.high >> sr;
+ * r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ * }
+ * else // n_uword_bits + 1 <= sr <= n_udword_bits - 1
+ * {
+ * q.s.low = n.s.low << (n_udword_bits - sr);
+ * q.s.high = (n.s.high << (n_udword_bits - sr)) |
+ * (n.s.low >> (sr - n_uword_bits));
+ * r.s.high = 0;
+ * r.s.low = n.s.high >> (sr - n_uword_bits);
+ * }
+ */
+ q.s.low = (n.s.low << (n_udword_bits - sr)) &
+ ((si_int)(n_uword_bits - sr) >> (n_uword_bits-1));
+ q.s.high = ((n.s.low << ( n_uword_bits - sr)) &
+ ((si_int)(sr - n_uword_bits - 1) >> (n_uword_bits-1))) |
+ (((n.s.high << (n_udword_bits - sr)) |
+ (n.s.low >> (sr - n_uword_bits))) &
+ ((si_int)(n_uword_bits - sr) >> (n_uword_bits-1)));
+ r.s.high = (n.s.high >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1));
+ r.s.low = ((n.s.high >> (sr - n_uword_bits)) &
+ ((si_int)(n_uword_bits - sr - 1) >> (n_uword_bits-1))) |
+ (((n.s.high << (n_uword_bits - sr)) |
+ (n.s.low >> sr)) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1)));
+ }
+ else
+ {
+ /* K X
+ * ---
+ * K K
+ */
+ sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
+ /* 0 <= sr <= n_uword_bits - 1 or sr large */
+ if (sr > n_uword_bits - 1)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_uword_bits */
+ /* q.all = n.all << (n_udword_bits - sr); */
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_uword_bits - sr);
+ /* r.all = n.all >> sr;
+ * if (sr < n_uword_bits)
+ * {
+ * r.s.high = n.s.high >> sr;
+ * r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
+ * }
+ * else
+ * {
+ * r.s.high = 0;
+ * r.s.low = n.s.high;
+ * }
+ */
+ r.s.high = (n.s.high >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1));
+ r.s.low = (n.s.high << (n_uword_bits - sr)) |
+ ((n.s.low >> sr) &
+ ((si_int)(sr - n_uword_bits) >> (n_uword_bits-1)));
+ }
+ }
+ /* Not a special case
+ * q and r are initialized with:
+ * q.all = n.all << (n_udword_bits - sr);
+ * r.all = n.all >> sr;
+ * 1 <= sr <= n_udword_bits - 1
+ */
+ su_int carry = 0;
+ for (; sr > 0; --sr)
+ {
+ /* r:q = ((r:q) << 1) | carry */
+ r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1));
+ r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1));
+ q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1));
+ q.s.low = (q.s.low << 1) | carry;
+ /* carry = 0;
+ * if (r.all >= d.all)
+ * {
+ * r.all -= d.all;
+ * carry = 1;
+ * }
+ */
+ const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
+ carry = s & 1;
+ r.all -= d.all & s;
+ }
+ q.all = (q.all << 1) | carry;
+ if (rem)
+ *rem = r.all;
+ return q.all;
+}
diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp
index b63a86aa..35d99dad 100755
--- a/system/lib/embind/bind.cpp
+++ b/system/lib/embind/bind.cpp
@@ -1,34 +1,80 @@
#include <emscripten/bind.h>
+#ifdef USE_CXA_DEMANGLE
+#include <../lib/libcxxabi/include/cxxabi.h>
+#endif
+#include <list>
+#include <vector>
+#include <typeinfo>
+#include <algorithm>
+#include <emscripten/emscripten.h>
+#include <climits>
using namespace emscripten;
-namespace emscripten {
- namespace internal {
- void registerStandardTypes() {
- static bool first = true;
- if (first) {
- first = false;
-
- _embind_register_void(getTypeID<void>(), "void");
-
- _embind_register_bool(getTypeID<bool>(), "bool", true, false);
-
- _embind_register_integer(getTypeID<char>(), "char");
- _embind_register_integer(getTypeID<signed char>(), "signed char");
- _embind_register_integer(getTypeID<unsigned char>(), "unsigned char");
- _embind_register_integer(getTypeID<signed short>(), "short");
- _embind_register_integer(getTypeID<unsigned short>(), "unsigned short");
- _embind_register_integer(getTypeID<signed int>(), "int");
- _embind_register_integer(getTypeID<unsigned int>(), "unsigned int");
- _embind_register_integer(getTypeID<signed long>(), "long");
- _embind_register_integer(getTypeID<unsigned long>(), "unsigned long");
-
- _embind_register_float(getTypeID<float>(), "float");
- _embind_register_float(getTypeID<double>(), "double");
-
- _embind_register_cstring(getTypeID<std::string>(), "std::string");
- _embind_register_emval(getTypeID<val>(), "emscripten::val");
- }
+extern "C" {
+ const char* __attribute__((used)) __getTypeName(const std::type_info* ti) {
+#ifdef USE_CXA_DEMANGLE
+ int stat;
+ char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat);
+ if (stat == 0 && demangled) {
+ return demangled;
}
+
+ switch (stat) {
+ case -1:
+ return strdup("<allocation failure>");
+ case -2:
+ return strdup("<invalid C++ symbol>");
+ case -3:
+ return strdup("<invalid argument>");
+ default:
+ return strdup("<unknown error>");
+ }
+#else
+ return strdup(ti->name());
+#endif
+ }
+}
+
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemset(wchar_t *dest, wchar_t c, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *o++ = c;
+ }
+ return dest;
+}
+
+// TODO: fix in library.js or a proper emscripten libc
+extern "C" wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, size_t count) {
+ wchar_t *o = dest;
+ while (count--) {
+ *dest++ = *src++;
}
+ return dest;
+}
+
+EMSCRIPTEN_BINDINGS(native_and_builtin_types) {
+ using namespace emscripten::internal;
+
+ _embind_register_void(TypeID<void>::get(), "void");
+
+ _embind_register_bool(TypeID<bool>::get(), "bool", true, false);
+
+ _embind_register_integer(TypeID<char>::get(), "char", CHAR_MIN, CHAR_MAX);
+ _embind_register_integer(TypeID<signed char>::get(), "signed char", SCHAR_MIN, SCHAR_MAX);
+ _embind_register_integer(TypeID<unsigned char>::get(), "unsigned char", 0, UCHAR_MAX);
+ _embind_register_integer(TypeID<signed short>::get(), "short", SHRT_MIN, SHRT_MAX);
+ _embind_register_integer(TypeID<unsigned short>::get(), "unsigned short", 0, USHRT_MAX);
+ _embind_register_integer(TypeID<signed int>::get(), "int", INT_MIN, INT_MAX);
+ _embind_register_integer(TypeID<unsigned int>::get(), "unsigned int", 0, UINT_MAX);
+ _embind_register_integer(TypeID<signed long>::get(), "long", LONG_MIN, LONG_MAX);
+ _embind_register_integer(TypeID<unsigned long>::get(), "unsigned long", 0, ULONG_MAX);
+
+ _embind_register_float(TypeID<float>::get(), "float");
+ _embind_register_float(TypeID<double>::get(), "double");
+
+ _embind_register_std_string(TypeID<std::string>::get(), "std::string");
+ _embind_register_std_wstring(TypeID<std::wstring>::get(), sizeof(wchar_t), "std::wstring");
+ _embind_register_emval(TypeID<val>::get(), "emscripten::val");
}