From 4bdc1b05e88e5eb51695a3325d07577d8fda46ed Mon Sep 17 00:00:00 2001 From: Tom Fairfield Date: Thu, 2 May 2013 21:34:20 -0300 Subject: [PATCH 01/39] fixes strcat so that it returns the correct value It should return the "dest" pointer that was passed in. test_strings has been updated with a test for the correct behavior. --- AUTHORS | 1 + src/library.js | 5 +++-- tests/runner.py | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 43ea83ddc5102..204b1741fa8e4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -70,3 +70,4 @@ a license to everyone to use it as detailed in LICENSE.) * Todd Lee (copyright owned by IMVU) * Anthony Pesch * Robert Bragg (copyright owned by Intel Corporation) +* Tom Fairfield diff --git a/src/library.js b/src/library.js index 3a966ec84bd0d..3983f52bffd78 100644 --- a/src/library.js +++ b/src/library.js @@ -4442,9 +4442,10 @@ LibraryManager.library = { strcat: function(pdest, psrc) { pdest = pdest|0; psrc = psrc|0; var i = 0; - pdest = (pdest + (_strlen(pdest)|0))|0; + var pdestEnd = 0; + pdestEnd = (pdest + _strlen(pdest))|0; do { - {{{ makeCopyValues('pdest+i', 'psrc+i', 1, 'i8', null, 1) }}}; + {{{ makeCopyValues('pdestEnd+i', 'psrc+i', 1, 'i8', null, 1) }}}; i = (i+1)|0; } while ({{{ makeGetValueAsm('psrc', 'i-1', 'i8') }}}); return pdest|0; diff --git a/tests/runner.py b/tests/runner.py index b3f88ea0629bb..5a53c0593c30d 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2051,8 +2051,9 @@ def test_strings(self): char *two = "fa la sa ho fi FI FO FUM WHEN WHERE WHY HOW WHO"; char three[1000]; strcpy(three, &one[argc*2]); - strcat(three, &two[argc*3]); + char *four = strcat(three, &two[argc*3]); printf("cat |%s|\\n", three); + printf("returned |%s|\\n", four); } return 0; @@ -2062,7 +2063,8 @@ def test_strings(self): print named Settings.NAMED_GLOBALS = named self.do_run(src, '''4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\nwaka ....e 1 O...wo 2 T................................ -cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too', '74']) +cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO| +returned |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too', '74']) if self.emcc_args == []: gen = open(self.in_dir('src.cpp.o.js')).read() assert ('var __str1;' in gen) == named From 6566a0c989b101572c8154bbd43cc6a07532bada Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 18 Apr 2013 16:52:42 -0700 Subject: [PATCH 02/39] Add a select_const for selecting the const method implementation if there are only two. Conflicts: tests/embind/embind_test.cpp --- system/include/emscripten/bind.h | 13 + tests/embind/embind_test.cpp | 4257 +++++++++++++++--------------- 2 files changed, 2156 insertions(+), 2114 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 4d2f4ac801e91..d5b2fe6a49b0f 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -224,6 +224,10 @@ namespace emscripten { struct allow_raw_pointer : public allow_raw_pointers { }; + //////////////////////////////////////////////////////////////////////////////// + // select_overload and select_const + //////////////////////////////////////////////////////////////////////////////// + template typename std::add_pointer::type select_overload(typename std::add_pointer::type fn) { return fn; @@ -241,6 +245,15 @@ namespace emscripten { return fn; } + template + auto select_const(ReturnType (ClassType::*method)(Args...) const) -> decltype(method) { + return method; + } + + //////////////////////////////////////////////////////////////////////////////// + // Invoker + //////////////////////////////////////////////////////////////////////////////// + namespace internal { template struct Invoker { diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index f2359955bc6e4..48da45b8a5e6b 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1,2114 +1,2143 @@ -#include -#include -#include -#include - -using namespace emscripten; - -val emval_test_mallinfo() { - const auto& i = mallinfo(); - val rv(val::object()); - rv.set("arena", val(i.arena)); - rv.set("ordblks", val(i.ordblks)); - rv.set("smblks", val(i.smblks)); - rv.set("hblks", val(i.hblks)); - rv.set("usmblks", val(i.usmblks)); - rv.set("fsmblks", val(i.fsmblks)); - rv.set("uordblks", val(i.uordblks)); - rv.set("fordblks", val(i.fordblks)); - rv.set("keepcost", val(i.keepcost)); - return rv; -} - -val emval_test_new_integer() { - return val(15); -} - -val emval_test_new_string() { - return val("Hello everyone"); -} - -std::string emval_test_get_string_from_val(val v) { - return v["key"].as(); -} - -val emval_test_new_object() { - val rv(val::object()); - rv.set("foo", val("bar")); - rv.set("baz", val(1)); - return rv; -} - -unsigned emval_test_passthrough_unsigned(unsigned v) { - return v; -} - -val emval_test_passthrough(val v) { - return v; -} - -void emval_test_return_void() { -} - -bool emval_test_not(bool b) { - return !b; -} - -unsigned emval_test_as_unsigned(val v) { - return v.as(); -} - -unsigned emval_test_get_length(val v) { - return v["length"].as(); -} - -double emval_test_add(char c, signed char sc, unsigned char uc, signed short ss, unsigned short us, signed int si, unsigned int ui, signed long sl, unsigned long ul, float f, double d) { - return c + sc + uc + ss + us + si + ui + sl + ul + f + d; -} - -float const_ref_adder(const int& i, const float& f) { - return i + f; -} - -unsigned emval_test_sum(val v) { - unsigned length = v["length"].as(); - double rv = 0; - for (unsigned i = 0; i < length; ++i) { - rv += v[i].as(); - } - return rv; -} - -std::string get_non_ascii_string() { - char c[128 + 1]; - c[128] = 0; - for (int i = 0; i < 128; ++i) { - c[i] = 128 + i; - } - return c; -} - -std::wstring get_non_ascii_wstring() { - std::wstring ws(4, 0); - ws[0] = 10; - ws[1] = 1234; - ws[2] = 2345; - ws[3] = 65535; - return ws; -} - -std::string emval_test_take_and_return_const_char_star(const char* str) { - return str; -} - -std::string emval_test_take_and_return_std_string(std::string str) { - return str; -} - -std::string emval_test_take_and_return_std_string_const_ref(const std::string& str) { - return str; -} - -std::wstring take_and_return_std_wstring(std::wstring str) { - return str; -} - -std::function emval_test_get_function_ptr() { - return emval_test_take_and_return_std_string; -} - -std::string emval_test_take_and_call_functor(std::function func) { - return func("asdf"); -} - -class ValHolder { -public: - ValHolder(val v) - : v_(v) - {} - - val getVal() const { - return v_; - } - - val getValNonConst() { - return v_; - } - - const val getConstVal() const { - return v_; - } - - const val& getValConstRef() const { - return v_; - } - - void setVal(val v) { - this->v_ = v; - } - - static int some_class_method(int i) { - return i; - } - - static const ValHolder* makeConst(val v) { - return new ValHolder(v); - } - - static ValHolder makeValHolder(val v) { - return ValHolder(v); - } - - static void set_via_raw_pointer(ValHolder* vh, val v) { - vh->setVal(v); - } - - static val get_via_raw_pointer(const ValHolder* vh) { - return vh->getVal(); - } - - static void transfer_via_raw_pointer(ValHolder* target, const ValHolder* source) { - target->setVal(source->getVal()); - } - - static val getValNonMember(const ValHolder& target) { - return target.getVal(); - } - -private: - val v_; -}; - -ValHolder emval_test_return_ValHolder() { - return val::object(); -} - -void emval_test_set_ValHolder_to_empty_object(ValHolder& vh) { - vh.setVal(val::object()); -} - -class StringHolder { -public: - StringHolder(const std::string& s) - : str_(s) - {} - - void set(const std::string& s) { - str_ = s; - } - - std::string get() const { - return str_; - } - - std::string& get_ref() { - return str_; - } - - const std::string& get_const_ref() const { - return str_; - } - -private: - std::string str_; -}; - -class SharedPtrHolder { -public: - SharedPtrHolder() - : ptr_(new StringHolder("a string")) - {} - - std::shared_ptr get() const { - return ptr_; - } - - void set(std::shared_ptr p) { - ptr_ = p; - } -private: - std::shared_ptr ptr_; -}; - -class VectorHolder { -public: - VectorHolder() { - v_.push_back(StringHolder("string #1")); - v_.push_back(StringHolder("string #2")); - } - - std::vector get() const { - return v_; - } - - void set(std::vector vec) { - v_ = vec; - } - -private: - std::vector v_; -}; - -class SmallClass { -public: - SmallClass(): member(7) {}; - int member; -}; - -class BigClass { -public: - BigClass(): member(11) {}; - int member; - int otherMember; - int yetAnotherMember; - - int getMember() { - return member; - } -}; - -class ParentClass { -public: - ParentClass(): bigClass() {}; - - BigClass bigClass; - - const BigClass& getBigClass() { - return bigClass; - }; -}; - -template -class TemplateClass { -public: - TemplateClass(T a, T b, T c) { - members[0] = a; - members[1] = b; - members[2] = c; - }; - - const T getMember(int n) { - return members[n]; - } - -protected: - T members[3]; -}; - -class ContainsTemplatedMemberClass { -public: - ContainsTemplatedMemberClass(): testTemplate(86, 87, 88) {}; - - TemplateClass testTemplate; - - const TemplateClass& getTestTemplate() { - return testTemplate; - }; -}; - -// Begin Inheritance Hierarchy Class Definitions - -class Base { -public: - Base(): name("Base"), - member(0), - baseMember(0) - {} - - std::string getClassName() const { - return name; - } - std::string getClassNameFromBase() const { - return name; - } - std::string getClassNameNotAvailableInDerivedClasses() { - // but wait -- if you act now we will throw in a SECOND base class method ABSOLUTELY FREE!! - return name; - } - void setMember(int value) { - member = value; - } - int getMember() { - return member; - } - void setBaseMember(int value) { - baseMember = value; - } - int getBaseMember() { - return baseMember; - } - std::string name; - int member; - int baseMember; -}; - -class SecondBase { -public: - SecondBase() - : name("SecondBase"), - member(0), - secondBaseMember(0) - {} - - std::string getClassName() const { - return name; - } - std::string getClassNameNotAvailableInDerivedClasses() { - return name; - } - std::string getClassNameFromSecondBase() const { - return name; - } - void setMember(int value) { - member = value; - } - int getMember() { - return member; - } - void setSecondBaseMember(int value) { - secondBaseMember = value; - } - int getSecondBaseMember() { - return secondBaseMember; - } - std::string name; - int member; - int secondBaseMember; -}; - -class Derived : public Base{ -public: - Derived() - : Base() - , member(0) - , name_("Derived") - {} - - std::string getClassName() const { - return name_; - } - void setMember(int value) { - member = value; - } - int getMember() { - return member; - } - int member; -private: - std::string name_; -}; - -class DerivedHolder { -public: - DerivedHolder() { - derived_.reset(); - } - void newDerived() { - deleteDerived(); - derived_ = std::shared_ptr(new Derived()); - } - void deleteDerived() { - derived_.reset(); - } - std::shared_ptr getDerived() { - return derived_; - } - std::string getDerivedClassName() { - return derived_->getClassName(); - } -private: - std::shared_ptr derived_; -}; - -class SiblingDerived : public Base { -public: - SiblingDerived() - : Base(), - name_("SiblingDerived") - {} - - std::string getClassName() const { - return name_; - } - -private: - std::string name_; -}; - -class MultiplyDerived : public Base, public SecondBase { -public: - MultiplyDerived() - : Base(), SecondBase(), - name_("MultiplyDerived") - { instanceCount_ ++; } - - ~MultiplyDerived() - { instanceCount_ --; } - - std::string getClassName() const { - return name_; - } - - static int getInstanceCount() { - return instanceCount_; - } -private: - std::string name_; - static int instanceCount_; -}; -int MultiplyDerived::instanceCount_ = 0; - -class DerivedTwice : public Derived { -public: - DerivedTwice() - : Derived(), - name_("DerivedTwice") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class DerivedTwiceNotBound : public Derived { -public: - DerivedTwiceNotBound() - : Derived(), - name_("DerivedTwiceNotBound") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class DerivedThrice: public DerivedTwiceNotBound { -public: - DerivedThrice() - : DerivedTwiceNotBound(), - name_("DerivedThrice") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class DerivedFourTimesNotBound: public DerivedThrice { -public: - DerivedFourTimesNotBound() - : DerivedThrice(), - name_("DerivedFourTimesNotBound") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyBase { -public: - PolyBase(const std::string& s) - : str_(s), - name_("PolyBase") - {} - - PolyBase(): name_("PolyBase") {} - - virtual ~PolyBase() {} - - virtual std::string virtualGetClassName() const { - return name_; - } - - std::string getClassName() const { - return name_; - } - -private: - std::string str_; - std::string name_; -}; - -class PolySecondBase { -public: - PolySecondBase(): name_("PolySecondBase") - {} - - virtual ~PolySecondBase() {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDerived : public PolyBase{ -public: - PolyDerived() - : PolyBase("PolyDerived"), - name_("PolyDerived") - {} - - std::string virtualGetClassName() const { - return name_; - } - - std::string getClassName() const { - return name_; - } - - static void setPtrDerived() { - ptr_ = std::shared_ptr(new PolyDerived()); - } - - static void releasePtr() { - ptr_.reset(); - } - - static std::string getPtrClassName() { - return ptr_->getClassName(); - } - - static std::shared_ptr getPtr() { - return ptr_; - } - -private: - std::string name_; - static std::shared_ptr ptr_; -}; -std::shared_ptr PolyDerived::ptr_; - -class PolySiblingDerived : public PolyBase { -public: - PolySiblingDerived() - : PolyBase(), - name_("PolySiblingDerived") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyMultiplyDerived : public PolyBase, public PolySecondBase { -public: - PolyMultiplyDerived() - : PolyBase(), PolySecondBase(), - name_("PolyMultiplyDerived") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDerivedTwiceWithoutSmartPointer: public PolyDerived { -public: - PolyDerivedTwiceWithoutSmartPointer() - : PolyDerived(), - name_("PolyDerivedTwiceWithoutSmartPointer") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDerivedTwiceNotBound : public PolyDerived { -public: - PolyDerivedTwiceNotBound() - : PolyDerived(), - name_("PolyDerivedTwiceNotBound") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDerivedThrice: public PolyDerivedTwiceNotBound { -public: - PolyDerivedThrice() - : PolyDerivedTwiceNotBound(), - name_("PolyDerivedThrice") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDerivedFourTimesNotBound: public PolyDerivedThrice { -public: - PolyDerivedFourTimesNotBound() - : PolyDerivedThrice(), - name_("PolyDerivedFourTimesNotBound") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDiamondBase { -public: - PolyDiamondBase(): - name_("PolyBase") - {} - ~PolyDiamondBase() {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDiamondDerived: public PolyDiamondBase { -public: - PolyDiamondDerived() - : PolyDiamondBase(), - name_("PolyDiamondDerived") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDiamondSiblingDerived: public PolyDiamondBase { -public: - PolyDiamondSiblingDerived() - : PolyDiamondBase(), - name_("PolyDiamondSiblingDerived") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -class PolyDiamondMultiplyDerived: public PolyDiamondDerived, public PolyDiamondSiblingDerived { -public: - PolyDiamondMultiplyDerived() - : PolyDiamondDerived(), PolyDiamondSiblingDerived(), - name_("PolyDiamondMultiplyDerived") - {} - - std::string getClassName() const { - return name_; - } -private: - std::string name_; -}; - -// End Inheritance Hierarchy Class Definitions - -std::map embind_test_get_string_int_map() { - std::map m; - - m["one"] = 1; - m["two"] = 2; - - return m; -}; - -struct Vector { - Vector() = delete; - - Vector(float x_, float y_, float z_, float w_) - : x(x_) - , y(y_) - , z(z_) - , w(w_) - {} - - float x, y, z, w; - - float& operator[](int i) { - return (&x)[i]; - } - - const float& operator[](int i) const { - return (&x)[i]; - } - - float getY() const { - return y; - } - void setY(float _y) { - y = _y; - } -}; - -struct DummyDataToTestPointerAdjustment { - std::string dummy; -}; - -struct TupleVector : DummyDataToTestPointerAdjustment, Vector { - TupleVector(): Vector(0, 0, 0, 0) {} - TupleVector(float x, float y, float z, float w): Vector(x, y, z, w) {} -}; - -struct StructVector : DummyDataToTestPointerAdjustment, Vector { - StructVector(): Vector(0, 0, 0, 0) {} - StructVector(float x, float y, float z, float w): Vector(x, y, z, w) {} -}; - -float readVectorZ(const Vector& v) { - return v.z; -} - -void writeVectorZ(Vector& v, float z) { - v.z = z; -} - -struct TupleVectorTuple { - TupleVector v = TupleVector(0, 0, 0, 0); -}; - -TupleVector emval_test_return_TupleVector() { - return TupleVector(1, 2, 3, 4); -} - -TupleVector emval_test_take_and_return_TupleVector(TupleVector v) { - return v; -} - -TupleVectorTuple emval_test_return_TupleVectorTuple() { - TupleVectorTuple cvt; - cvt.v = emval_test_return_TupleVector(); - return cvt; -} - -StructVector emval_test_return_StructVector() { - return StructVector(1, 2, 3, 4); -} - -StructVector emval_test_take_and_return_StructVector(StructVector v) { - return v; -} - -struct CustomStruct { - CustomStruct() - : field(10) - {} - - const int& getField() const { - return field; - } - - int field; -}; - -struct TupleInStruct { - TupleVector field; -}; - -TupleInStruct emval_test_take_and_return_TupleInStruct(TupleInStruct cs) { - return cs; -} - -enum Enum { ONE, TWO }; - -Enum emval_test_take_and_return_Enum(Enum e) { - return e; -} - -enum class EnumClass { ONE, TWO }; - -EnumClass emval_test_take_and_return_EnumClass(EnumClass e) { - return e; -} - -void emval_test_call_function(val v, int i, float f, TupleVector tv, StructVector sv) { - v(i, f, tv, sv); -} - -std::unique_ptr emval_test_return_unique_ptr() { - return std::unique_ptr(new ValHolder(val::object())); -} - -std::shared_ptr emval_test_return_shared_ptr() { - return std::shared_ptr(new ValHolder(val::object())); -} - -std::shared_ptr emval_test_return_empty_shared_ptr() { - return std::shared_ptr(); -} - -bool emval_test_is_shared_ptr_null(std::shared_ptr p) { - return !p; -} - -static SmallClass smallClass; -static BigClass bigClass; - -SmallClass embind_test_return_small_class_instance() { - return smallClass; -} - -BigClass embind_test_return_big_class_instance() { - return bigClass; -} - -int embind_test_accept_small_class_instance(SmallClass c) { - return c.member; -} - -int embind_test_accept_big_class_instance(BigClass c) { - return c.member; -} - -// Begin Inheritance Hierarchy Test Wrappers - -Base* embind_test_return_raw_base_ptr() { - return new Base(); -} - -Base* embind_test_return_raw_derived_ptr_as_base() { - return new Derived(); -} - -Base* embind_test_return_raw_sibling_derived_ptr_as_base() { - return new SiblingDerived(); -} - -PolyBase* embind_test_return_raw_polymorphic_derived_ptr_as_base() { - return new PolyDerived(); -} - -PolyBase* embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base() { - return new PolySiblingDerived(); -} - -PolyBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base() { - return new PolyMultiplyDerived(); -} - -PolySecondBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base() { - return new PolyMultiplyDerived(); -} - -PolyBase* embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base() { - return new PolyDerivedFourTimesNotBound(); -} - -std::shared_ptr embind_test_return_smart_base_ptr() { - return std::shared_ptr(new Base()); -} - -std::shared_ptr embind_test_return_smart_polymorphic_base_ptr() { - return std::shared_ptr(new PolyBase("PolyBase")); -} - -std::shared_ptr embind_test_return_smart_derived_ptr() { - return std::shared_ptr(new Derived()); -} - -std::shared_ptr embind_test_return_smart_sibling_derived_ptr() { - return std::shared_ptr(new SiblingDerived()); -} - -std::shared_ptr embind_test_return_smart_multiply_derived_ptr() { - return std::shared_ptr(new MultiplyDerived()); -} - -std::shared_ptr embind_test_return_smart_derived_thrice_ptr() { - return std::shared_ptr(new DerivedThrice()); -} - -std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr() { - return std::shared_ptr(new PolyDerived()); -} - -std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr() { - return std::shared_ptr(new PolySiblingDerived()); -} - -std::shared_ptr embind_test_return_smart_polymorphic_multiply_derived_ptr() { - return std::shared_ptr(new PolyMultiplyDerived()); -} - -std::shared_ptr embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base() { - return std::shared_ptr(new PolyDerivedTwiceWithoutSmartPointer()); -} - -std::shared_ptr embind_test_return_smart_poly_derived_thrice_ptr() { - return std::shared_ptr(new PolyDerivedThrice()); -} - -std::shared_ptr embind_test_return_smart_derived_ptr_as_base() { - return std::shared_ptr(new PolyDerived()); -} - -val embind_test_return_smart_derived_ptr_as_val() { - return val(std::shared_ptr(new PolyDerived())); -} - -std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr_as_base() { - return std::shared_ptr(new PolyDerived()); -} - -std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base() { - return std::shared_ptr(new PolySiblingDerived()); -} - -std::string embind_test_get_class_name_via_base_ptr(Base *p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_second_base_ptr(SecondBase *p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_polymorphic_base_ptr(PolyBase *p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_polymorphic_second_base_ptr(PolySecondBase *p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_smart_base_ptr(std::shared_ptr p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_reference_to_smart_base_ptr(std::shared_ptr& p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_smart_second_base_ptr(std::shared_ptr p) { - return p->getClassName(); -} - -std::string embind_test_get_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { - return p->getClassName(); -} - -std::string embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { - return p->virtualGetClassName(); -} - -std::string embind_test_get_class_name_via_smart_polymorphic_second_base_ptr(std::shared_ptr p) { - return p->getClassName(); -} - -void embind_modify_smart_pointer_passed_by_reference(std::shared_ptr& p) { - p = std::shared_ptr(new Base()); - p->name = "Changed"; -} - -void embind_attempt_to_modify_smart_pointer_when_passed_by_value(std::shared_ptr p) { - p = std::shared_ptr(new Base()); - p->name = "Changed"; -} - -static std::shared_ptr savedBasePointer; - -void embind_save_smart_base_pointer(std::shared_ptr p) { - savedBasePointer = p; -} - -// End Inheritance Hierarchy Test Wrappers - -std::vector emval_test_return_vector() { - int myints[] = { 10, 20, 30 }; - return std::vector(myints, myints + sizeof(myints) / sizeof(int)); -} - -std::vector > emval_test_return_vector_of_vectors() { - int myints1[] = { 10, 20, 30 }; - int myints2[] = { 40, 50, 60 }; - std::vector vec1(myints1, myints1 + sizeof(myints1) / sizeof(int)); - std::vector vec2(myints2, myints2 + sizeof(myints2) / sizeof(int)); - std::vector>vec3; - vec3.emplace_back(vec1); - vec3.emplace_back(vec2); - return vec3; -} - -std::vector> emval_test_return_shared_ptr_vector() { - std::vector> sharedStrVector; - sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #1"))); - sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #2"))); - - return sharedStrVector; -} - -void test_string_with_vec(const std::string& p1, std::vector& v1) { - // THIS DOES NOT WORK -- need to get as val and then call vecFromJSArray - printf("%s\n", p1.c_str()); -} - -val embind_test_new_Object() { - return val::global("Object").new_(); -} - -val embind_test_new_factory(val factory, val argument) { - return factory.new_(10, std::string("hello"), argument); -} - -class AbstractClass { -public: - virtual ~AbstractClass() {} - virtual std::string abstractMethod() const = 0; - virtual std::string optionalMethod(std::string s) const { - return "optional" + s; - } -}; - -EMSCRIPTEN_SYMBOL(optionalMethod); - -class AbstractClassWrapper : public wrapper { -public: - EMSCRIPTEN_WRAPPER(AbstractClassWrapper); - - std::string abstractMethod() const { - return call("abstractMethod"); - } - std::string optionalMethod(std::string s) const { - return optional_call(optionalMethod_symbol, [&] { - return AbstractClass::optionalMethod(s); - }, s); - } -}; - -class ConcreteClass : public AbstractClass { - std::string abstractMethod() const { - return "from concrete"; - } -}; - -std::shared_ptr getAbstractClass() { - return std::make_shared(); -} - -std::string callAbstractMethod(AbstractClass& ac) { - return ac.abstractMethod(); -} - -std::string callOptionalMethod(AbstractClass& ac, std::string s) { - return ac.optionalMethod(s); -} - -class HasExternalConstructor { -public: - HasExternalConstructor(const std::string& str) - : m(str) - {} - - std::string getString() const { - return m; - } - - std::string m; -}; - -HasExternalConstructor* createHasExternalConstructor(const std::string& str) { - return new HasExternalConstructor(str); -} - -template -class CustomSmartPtr { -public: - CustomSmartPtr() - : CustomSmartPtr(nullptr) - { - std::fill(d_, d_ + N_, Valid); - } - - explicit CustomSmartPtr(T* t) - : ptr_(t) - { - std::fill(d_, d_ + N_, Valid); - } - - CustomSmartPtr(const CustomSmartPtr& other) - : ptr_(other.ptr_) - { - other.verify(); - std::fill(d_, d_ + N_, Valid); - if (ptr_) { - ++(ptr_->refcount); - } - } - - ~CustomSmartPtr() { - verify(); - std::fill(d_, d_ + N_, Deleted); - - if (ptr_ && --ptr_->refcount == 0) { - delete ptr_; - } - } - - T* get_raw() const { - return ptr_; - } - -private: - void verify() const { - for (size_t i = 0; i < N_; ++i) { - if (d_[i] != Valid) { - abort(); - } - } - } - - enum { - Valid = 255, - Deleted = 127, - }; - static constexpr size_t N_ = 1000000; - unsigned char d_[N_]; - T* ptr_; - - CustomSmartPtr& operator=(const CustomSmartPtr&) = delete; -}; - -class HeldBySmartPtr { -public: - HeldBySmartPtr(int i, const std::string& s) - : i(i) - , s(s) - {} - - static CustomSmartPtr newCustomPtr(int i, const std::string& s) { - return CustomSmartPtr(new HeldBySmartPtr(i, s)); - } - - int refcount = 1; - int i; - std::string s; -}; - -HeldBySmartPtr takesHeldBySmartPtr(HeldBySmartPtr p) { - return p; -} -std::shared_ptr takesHeldBySmartPtrSharedPtr(std::shared_ptr p) { - return p; -} - -namespace emscripten { - template - struct smart_ptr_trait> { - typedef T element_type; - - static sharing_policy get_sharing_policy() { - return sharing_policy::NONE; - } - - static T* get(const CustomSmartPtr& p) { - return p.get_raw(); - } - - static CustomSmartPtr share(const CustomSmartPtr& r, T* ptr) { - ++ptr->refcount; // implement an adopt API? - return CustomSmartPtr(ptr); - } - }; -} - -typedef CustomSmartPtr HeldByCustomSmartPtrPtr; - -class HeldByCustomSmartPtr { -public: - HeldByCustomSmartPtr(int i, const std::string& s) - : i(i) - , s(s) - {} - - static HeldByCustomSmartPtrPtr create(int i, const std::string& s) { - return HeldByCustomSmartPtrPtr(new HeldByCustomSmartPtr(i, s)); - } - - static std::shared_ptr createSharedPtr(int i, const std::string& s) { - return std::make_shared(i, s); - }; - - int refcount = 1; - int i; - std::string s; -}; - -HeldByCustomSmartPtr* passThroughRawPtr(HeldByCustomSmartPtr* p) { - return p; -} -HeldByCustomSmartPtrPtr passThroughCustomSmartPtr(HeldByCustomSmartPtrPtr p) { - return p; -} - -struct Base1 { -public: - Base1(): field1("Base1") {} - std::string field1; - - std::string getField() const { - return field1; - } -}; - -struct Base2 { -public: - Base2(): field2("Base2") {} - std::string field2; - - std::string getField() const { - return field2; - } -}; - -struct HasTwoBases : public Base1, public Base2 { -}; - -val get_module_property(const std::string& s) { - return val::module_property(s.c_str()); -} - -std::string char_to_string(char ch) { - char str[256]; - sprintf(str, "%d", (int)ch); - return str; -} - -std::string signed_char_to_string(signed char ch) { - char str[256]; - sprintf(str, "%hhd", ch); - return str; -} - -std::string unsigned_char_to_string(unsigned char ch) { - char str[256]; - sprintf(str, "%hhu", ch); - return str; -} - -std::string short_to_string(short val) { - char str[256]; - sprintf(str, "%hd", val); - return str; -} - -std::string unsigned_short_to_string(unsigned short val) { - char str[256]; - sprintf(str, "%hu", val); - return str; -} - -std::string int_to_string(int val) { - char str[256]; - sprintf(str, "%d", val); - return str; -} - -std::string unsigned_int_to_string(unsigned int val) { - char str[256]; - sprintf(str, "%u", val); - return str; -} - -std::string long_to_string(long val) { - char str[256]; - sprintf(str, "%ld", val); - return str; -} - -std::string unsigned_long_to_string(unsigned long val) { - char str[256]; - sprintf(str, "%lu", val); - return str; -} - -class MultipleCtors { -public: - int value; - - MultipleCtors(int i) { - value = 1; - assert(i == 10); - } - MultipleCtors(int i, int j) { - value = 2; - assert(i == 20); - assert(j == 20); - } - MultipleCtors(int i, int j, int k) { - value = 3; - assert(i == 30); - assert(j == 30); - assert(k == 30); - } - - int WhichCtorCalled() const { - return value; - } -}; - -class MultipleOverloads { -public: - MultipleOverloads() {} - - int value; - static int staticValue; - - int Func(int i) { - assert(i == 10); - value = 1; - return 1; - } - int Func(int i, int j) { - assert(i == 20); - assert(j == 20); - value = 2; - return 2; - } - - int WhichFuncCalled() const { - return value; - } - - static int StaticFunc(int i) { - assert(i == 10); - staticValue = 1; - return 1; - } - static int StaticFunc(int i, int j) { - assert(i == 20); - assert(j == 20); - staticValue = 2; - return 2; - } - - static int WhichStaticFuncCalled() { - return staticValue; - } -}; - -class MultipleOverloadsDerived : public MultipleOverloads { -public: - MultipleOverloadsDerived() {} - - int Func(int i, int j, int k) { - assert(i == 30); - assert(j == 30); - assert(k == 30); - value = 3; - return 3; - } - int Func(int i, int j, int k, int l) { - assert(i == 40); - assert(j == 40); - assert(k == 40); - assert(l == 40); - value = 4; - return 4; - } - - static int StaticFunc(int i, int j, int k) { - assert(i == 30); - assert(j == 30); - assert(k == 30); - staticValue = 3; - return 3; - } - static int StaticFunc(int i, int j, int k, int l) { - assert(i == 40); - assert(j == 40); - assert(k == 40); - assert(l == 40); - staticValue = 4; - return 4; - } -}; - -int overloaded_function(int i) -{ - assert(i == 10); - return 1; -} - -int overloaded_function(int i, int j) -{ - assert(i == 20); - assert(j == 20); - return 2; -} - -EMSCRIPTEN_BINDINGS(constants) { - constant("INT_CONSTANT", 10); - constant("STRING_CONSTANT", std::string("some string")); - - TupleVector tv(1, 2, 3, 4); - constant("VALUE_TUPLE_CONSTANT", tv); - - StructVector sv(1, 2, 3, 4); - constant("VALUE_STRUCT_CONSTANT", sv); -} - -EMSCRIPTEN_BINDINGS(tests) { - register_vector("IntegerVector"); - register_vector("CharVector"); - register_vector("VectorUnsigned"); - register_vector("VectorUnsignedChar"); - register_vector("StringVector"); - register_vector("EmValVector"); - register_vector("FloatVector"); - register_vector>("IntegerVectorVector"); - - function("mallinfo", &emval_test_mallinfo); - function("emval_test_new_integer", &emval_test_new_integer); - function("emval_test_new_string", &emval_test_new_string); - function("emval_test_get_string_from_val", &emval_test_get_string_from_val); - function("emval_test_new_object", &emval_test_new_object); - function("emval_test_passthrough_unsigned", &emval_test_passthrough_unsigned); - function("emval_test_passthrough", &emval_test_passthrough); - function("emval_test_return_void", &emval_test_return_void); - function("emval_test_not", &emval_test_not); - - function("emval_test_as_unsigned", &emval_test_as_unsigned); - function("emval_test_get_length", &emval_test_get_length); - function("emval_test_add", &emval_test_add); - function("const_ref_adder", &const_ref_adder); - function("emval_test_sum", &emval_test_sum); - - function("get_non_ascii_string", &get_non_ascii_string); - function("get_non_ascii_wstring", &get_non_ascii_wstring); - //function("emval_test_take_and_return_const_char_star", &emval_test_take_and_return_const_char_star); - function("emval_test_take_and_return_std_string", &emval_test_take_and_return_std_string); - function("emval_test_take_and_return_std_string_const_ref", &emval_test_take_and_return_std_string_const_ref); - function("take_and_return_std_wstring", &take_and_return_std_wstring); - - //function("emval_test_take_and_return_CustomStruct", &emval_test_take_and_return_CustomStruct); - - value_tuple("TupleVector") - .element(&TupleVector::x) - .element(&Vector::getY, &Vector::setY) - .element(&readVectorZ, &writeVectorZ) - .element(index<3>()) - ; - - function("emval_test_return_TupleVector", &emval_test_return_TupleVector); - function("emval_test_take_and_return_TupleVector", &emval_test_take_and_return_TupleVector); - - value_tuple("TupleVectorTuple") - .element(&TupleVectorTuple::v) - ; - - function("emval_test_return_TupleVectorTuple", &emval_test_return_TupleVectorTuple); - - value_struct("StructVector") - .field("x", &StructVector::x) - .field("y", &Vector::getY, &Vector::setY) - .field("z", &readVectorZ, &writeVectorZ) - .field("w", index<3>()) - ; - - function("emval_test_return_StructVector", &emval_test_return_StructVector); - function("emval_test_take_and_return_StructVector", &emval_test_take_and_return_StructVector); - - value_struct("TupleInStruct") - .field("field", &TupleInStruct::field) - ; - - function("emval_test_take_and_return_TupleInStruct", &emval_test_take_and_return_TupleInStruct); - - class_("ValHolder") - .smart_ptr>() - .constructor() - .function("getVal", &ValHolder::getVal) - .function("getValNonConst", &ValHolder::getValNonConst) - .function("getConstVal", &ValHolder::getConstVal) - .function("getValConstRef", &ValHolder::getValConstRef) - .function("setVal", &ValHolder::setVal) - .property("val", &ValHolder::getVal, &ValHolder::setVal) - .property("val_readonly", &ValHolder::getVal) - .class_function("makeConst", &ValHolder::makeConst, allow_raw_pointer()) - .class_function("makeValHolder", &ValHolder::makeValHolder) - .class_function("some_class_method", &ValHolder::some_class_method) - .class_function("set_via_raw_pointer", - &ValHolder::set_via_raw_pointer, - allow_raw_pointer>()) - .class_function("get_via_raw_pointer", - &ValHolder::get_via_raw_pointer, - allow_raw_pointer>()) - .class_function("transfer_via_raw_pointer", - &ValHolder::transfer_via_raw_pointer, - allow_raw_pointers()) - - // non-member method - .function("setEmpty", &emval_test_set_ValHolder_to_empty_object) - .function("getValNonMember", &ValHolder::getValNonMember) - ; - - function("emval_test_return_ValHolder", &emval_test_return_ValHolder); - function("emval_test_set_ValHolder_to_empty_object", &emval_test_set_ValHolder_to_empty_object); - - class_>("StringFunctorString") - .constructor<>() - .function("opcall", &std::function::operator()) - ; - - function("emval_test_get_function_ptr", &emval_test_get_function_ptr); - function("emval_test_take_and_call_functor", &emval_test_take_and_call_functor); - - class_("StringHolder") - .smart_ptr>() - .constructor() - .function("set", &StringHolder::set) - .function("get", &StringHolder::get) - .function("get_const_ref", &StringHolder::get_const_ref) - ; - - class_("SharedPtrHolder") - .constructor<>() - .function("get", &SharedPtrHolder::get) - .function("set", &SharedPtrHolder::set) - ; - - class_("SmallClass") - .constructor<>() - .property("member", &SmallClass::member) - ; - - class_("BigClass") - .constructor<>() - .property("member", &BigClass::member) - .property("otherMember", &BigClass::otherMember) - .property("yetAnotherMember", &BigClass::yetAnotherMember) - .function("getMember", &BigClass::getMember) - ; - - class_("ParentClass") - .constructor<>() - .function("getBigClass", &ParentClass::getBigClass) - ; - - class_>("IntTemplateClass") - .constructor() - .function("getMember", &TemplateClass::getMember) - ; - - class_("ContainsTemplatedMemberClass") - .constructor<>() - .function("getTestTemplate", &ContainsTemplatedMemberClass::getTestTemplate) - ; - - // register Derived before Base as a test that it's possible to - // register base classes afterwards - class_>("Derived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &Derived::getClassName) - .function("getMember", &Derived::getMember) - .function("setMember", &Derived::setMember) - .property("member", &Derived::member) - ; - - class_("Base") - .smart_ptr>() - .constructor<>() - .function("getClassName", &Base::getClassName) - .function("getClassNameFromBase", &Base::getClassNameFromBase) - .function("getClassNameNotAvailableInDerivedClasses", &Base::getClassNameNotAvailableInDerivedClasses) - .function("getMember", &Base::getMember) - .function("setMember", &Base::setMember) - .function("getBaseMember", &Base::getBaseMember) - .function("setBaseMember", &Base::setBaseMember) - .property("member", &Base::member) - .property("baseMember", &Base::baseMember) - ; - - class_("SecondBase") - .smart_ptr>() - .constructor<>() - .function("getClassName", &SecondBase::getClassName) - .function("getClassNameFromSecondBase", &SecondBase::getClassNameFromSecondBase) - .function("getClassNameNotAvailableInDerivedClasses", &SecondBase::getClassNameNotAvailableInDerivedClasses) - .function("getMember", &SecondBase::getMember) - .function("setMember", &SecondBase::setMember) - .function("getSecondBaseMember", &SecondBase::getSecondBaseMember) - .function("setSecondBaseMember", &SecondBase::setSecondBaseMember) - .property("member", &SecondBase::member) - .property("secondBaseMember", &SecondBase::secondBaseMember) - ; - - - class_("DerivedHolder") - .constructor<>() - .function("newDerived", &DerivedHolder::newDerived) - .function("deleteDerived", &DerivedHolder::deleteDerived) - .function("getDerived", &DerivedHolder::getDerived) - .function("getDerivedClassName", &DerivedHolder::getDerivedClassName) - ; - - class_("SiblingDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &SiblingDerived::getClassName) - ; - - class_>("MultiplyDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &MultiplyDerived::getClassName) - .class_function("getInstanceCount", &MultiplyDerived::getInstanceCount) - ; - - class_ >("DerivedTwice") - .constructor<>() - .function("getClassName", &DerivedTwice::getClassName) - ; - - class_ >("DerivedThrice") - .smart_ptr>() - .constructor<>() - .function("getClassName", &DerivedThrice::getClassName) - ; - - class_("PolyBase") - .smart_ptr>() - .constructor<>() - .function("virtualGetClassName", &PolyBase::virtualGetClassName) - .function("getClassName", &PolyBase::getClassName) - ; - - class_("PolySecondBase") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolySecondBase::getClassName) - ; - - class_>("PolyDerived") - .smart_ptr>() - .constructor<>() - .function("virtualGetClassName", &PolyDerived::virtualGetClassName) - .function("getClassName", &PolyDerived::getClassName) - .class_function("setPtrDerived", &PolyDerived::setPtrDerived) - .class_function("releasePtr", &PolyDerived::releasePtr) - .class_function("getPtrClassName", &PolyDerived::getPtrClassName) - .class_function("getPtr", &PolyDerived::getPtr) - ; -// static void setPtrDerived() { -// ptr = std::shared_ptr(new PolyDerived()); -// } -// -// static std::string getPtrClassName() { -// return ptr->getClassName(); -// } -// -// static std::shared_ptr getPtr() { -// return ptr; -// } - - class_>("PolySiblingDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolySiblingDerived::getClassName) - ; - - class_>("PolyMultiplyDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyMultiplyDerived::getClassName) - ; - - class_>("PolyDerivedThrice") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyDerivedThrice::getClassName) - ; - - class_("PolyDiamondBase") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyDiamondBase::getClassName) - ; - - class_("PolyDiamondDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyDiamondDerived::getClassName) - ; - - class_("PolyDiamondSiblingDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyDiamondSiblingDerived::getClassName) - ; - - class_("PolyDiamondMultiplyDerived") - .smart_ptr>() - .constructor<>() - .function("getClassName", &PolyDiamondMultiplyDerived::getClassName) - ; - - function("embind_test_return_small_class_instance", &embind_test_return_small_class_instance); - function("embind_test_return_big_class_instance", &embind_test_return_big_class_instance); - function("embind_test_accept_small_class_instance", &embind_test_accept_small_class_instance); - function("embind_test_accept_big_class_instance", &embind_test_accept_big_class_instance); - - function("embind_test_return_raw_base_ptr", embind_test_return_raw_base_ptr, allow_raw_pointer()); - function("embind_test_return_raw_derived_ptr_as_base", embind_test_return_raw_derived_ptr_as_base, allow_raw_pointer()); - function("embind_test_return_raw_sibling_derived_ptr_as_base", embind_test_return_raw_sibling_derived_ptr_as_base, allow_raw_pointer()); - function("embind_test_return_raw_polymorphic_derived_ptr_as_base", embind_test_return_raw_polymorphic_derived_ptr_as_base, allow_raw_pointer()); - function("embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base", embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base, allow_raw_pointer()); - function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base, allow_raw_pointer()); - function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base, allow_raw_pointer()); - function("embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base", embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base, allow_raw_pointer()); - function("embind_test_return_smart_derived_ptr", embind_test_return_smart_derived_ptr); - function("embind_test_return_smart_sibling_derived_ptr", embind_test_return_smart_sibling_derived_ptr); - function("embind_test_return_smart_multiply_derived_ptr", embind_test_return_smart_multiply_derived_ptr); - function("embind_test_return_smart_derived_thrice_ptr", embind_test_return_smart_derived_thrice_ptr); - function("embind_test_return_smart_base_ptr", embind_test_return_smart_base_ptr); - function("embind_test_return_smart_polymorphic_base_ptr", embind_test_return_smart_polymorphic_base_ptr); - function("embind_test_return_smart_polymorphic_derived_ptr", embind_test_return_smart_polymorphic_derived_ptr); - function("embind_test_return_smart_polymorphic_sibling_derived_ptr", embind_test_return_smart_polymorphic_sibling_derived_ptr); - function("embind_test_return_smart_polymorphic_multiply_derived_ptr", embind_test_return_smart_polymorphic_multiply_derived_ptr); - function("embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base", embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base); - function("embind_test_return_smart_poly_derived_thrice_ptr", embind_test_return_smart_poly_derived_thrice_ptr); - function("embind_test_return_smart_derived_ptr_as_base", embind_test_return_smart_derived_ptr_as_base); - function("embind_test_return_smart_derived_ptr_as_val", embind_test_return_smart_derived_ptr_as_val); - function("embind_test_return_smart_polymorphic_derived_ptr_as_base", embind_test_return_smart_polymorphic_derived_ptr_as_base); - function("embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base", embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base); - function("embind_test_get_class_name_via_base_ptr", embind_test_get_class_name_via_base_ptr, allow_raw_pointer>()); - function("embind_test_get_class_name_via_second_base_ptr", embind_test_get_class_name_via_second_base_ptr, allow_raw_pointer>()); - function("embind_test_get_class_name_via_polymorphic_base_ptr", embind_test_get_class_name_via_polymorphic_base_ptr, allow_raw_pointer>()); - function("embind_test_get_class_name_via_polymorphic_second_base_ptr", embind_test_get_class_name_via_polymorphic_second_base_ptr, allow_raw_pointer>()); - // todo: allow_raw_pointer should fail earlier if argument is not a pointer - function("embind_test_get_class_name_via_smart_base_ptr", embind_test_get_class_name_via_smart_base_ptr); - function("embind_test_get_class_name_via_reference_to_smart_base_ptr", embind_test_get_class_name_via_reference_to_smart_base_ptr); - function("embind_test_get_class_name_via_smart_second_base_ptr", embind_test_get_class_name_via_smart_second_base_ptr); - function("embind_test_get_class_name_via_smart_polymorphic_base_ptr", embind_test_get_class_name_via_smart_polymorphic_base_ptr); - function("embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr", embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr); - function("embind_test_get_class_name_via_smart_polymorphic_second_base_ptr", embind_test_get_class_name_via_smart_polymorphic_second_base_ptr); - function("embind_modify_smart_pointer_passed_by_reference", embind_modify_smart_pointer_passed_by_reference); - function("embind_attempt_to_modify_smart_pointer_when_passed_by_value", embind_attempt_to_modify_smart_pointer_when_passed_by_value); - function("embind_save_smart_base_pointer", embind_save_smart_base_pointer); - - class_("Base1") - .constructor() - .function("getField", &Base1::getField) - ; - - class_("Base2") - .function("getField", &Base2::getField) - .property("field", &Base2::field2) - ; - - class_>("HasTwoBases") - .constructor() - ; - - class_("CustomStruct") - .constructor<>() - .property("field", &CustomStruct::field) - .function("getField", &CustomStruct::getField) - ; - - enum_("Enum") - .value("ONE", ONE) - .value("TWO", TWO) - ; - function("emval_test_take_and_return_Enum", &emval_test_take_and_return_Enum); - - enum_("EnumClass") - .value("ONE", EnumClass::ONE) - .value("TWO", EnumClass::TWO) - ; - function("emval_test_take_and_return_EnumClass", &emval_test_take_and_return_EnumClass); - - function("emval_test_call_function", &emval_test_call_function); - - function("emval_test_return_unique_ptr", &emval_test_return_unique_ptr); - - function("emval_test_return_shared_ptr", &emval_test_return_shared_ptr); - function("emval_test_return_empty_shared_ptr", &emval_test_return_empty_shared_ptr); - function("emval_test_is_shared_ptr_null", &emval_test_is_shared_ptr_null); - - function("emval_test_return_vector", &emval_test_return_vector); - function("emval_test_return_vector_of_vectors", &emval_test_return_vector_of_vectors); - - register_vector>("SharedPtrVector"); - function("emval_test_return_shared_ptr_vector", &emval_test_return_shared_ptr_vector); - - function("get_module_property", &get_module_property); - - register_vector("StringHolderVector"); - class_("VectorHolder") - .constructor<>() - .function("get", &VectorHolder::get) - .function("set", &VectorHolder::set) - ; - - function("test_string_with_vec", &test_string_with_vec); - - register_map("StringIntMap"); - function("embind_test_get_string_int_map", embind_test_get_string_int_map); - - function("embind_test_new_Object", &embind_test_new_Object); - function("embind_test_new_factory", &embind_test_new_factory); - - class_("AbstractClass") - .smart_ptr>() - .allow_subclass() - .function("abstractMethod", &AbstractClass::abstractMethod) - .function("optionalMethod", &AbstractClass::optionalMethod) - ; - - function("getAbstractClass", &getAbstractClass); - function("callAbstractMethod", &callAbstractMethod); - function("callOptionalMethod", &callOptionalMethod); - - class_("HasExternalConstructor") - .constructor(&createHasExternalConstructor) - .function("getString", &HasExternalConstructor::getString) - ; - - auto HeldBySmartPtr_class = class_("HeldBySmartPtr"); - HeldBySmartPtr_class - .smart_ptr>() - .smart_ptr_constructor(&std::make_shared) - .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) - .function("returnThis", &takesHeldBySmartPtrSharedPtr) - .property("i", &HeldBySmartPtr::i) - .property("s", &HeldBySmartPtr::s) - ; - function("takesHeldBySmartPtr", &takesHeldBySmartPtr); - function("takesHeldBySmartPtrSharedPtr", &takesHeldBySmartPtrSharedPtr); - - class_("HeldByCustomSmartPtr") - .smart_ptr>() - .smart_ptr_constructor(&HeldByCustomSmartPtr::create) - .class_function("createSharedPtr", &HeldByCustomSmartPtr::createSharedPtr) - .property("i", &HeldByCustomSmartPtr::i) - .property("s", &HeldByCustomSmartPtr::s) - ; - - function("passThroughRawPtr", &passThroughRawPtr, allow_raw_pointers()); - function("passThroughCustomSmartPtr", &passThroughCustomSmartPtr); - - function("char_to_string", &char_to_string); - function("signed_char_to_string", &signed_char_to_string); - function("unsigned_char_to_string", &unsigned_char_to_string); - function("short_to_string", &short_to_string); - function("unsigned_short_to_string", &unsigned_short_to_string); - function("int_to_string", &int_to_string); - function("unsigned_int_to_string", &unsigned_int_to_string); - function("long_to_string", &long_to_string); - function("unsigned_long_to_string", &unsigned_long_to_string); - - function("overloaded_function", select_overload(&overloaded_function)); - function("overloaded_function", select_overload(&overloaded_function)); - - class_("MultipleCtors") - .constructor() - .constructor() - .constructor() - .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled); - - class_("MultipleOverloads") - .constructor<>() - .function("Func", select_overload(&MultipleOverloads::Func)) - .function("Func", select_overload(&MultipleOverloads::Func)) - .function("WhichFuncCalled", &MultipleOverloads::WhichFuncCalled) - .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) - .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) - .class_function("WhichStaticFuncCalled", &MultipleOverloads::WhichStaticFuncCalled) - ; - - class_ >("MultipleOverloadsDerived") - .constructor<>() - .function("Func", select_overload(&MultipleOverloadsDerived::Func)) - .function("Func", select_overload(&MultipleOverloadsDerived::Func)) - .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) - .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) - ; -} - -// tests for out-of-order registration - -class SecondElement { -}; - -class FirstElement { -}; - -struct OrderedTuple { - FirstElement first; - SecondElement second; -}; - -struct OrderedStruct { - FirstElement first; - SecondElement second; -}; - -OrderedTuple getOrderedTuple() { - return OrderedTuple(); -} - -OrderedStruct getOrderedStruct() { - return OrderedStruct(); -} - -EMSCRIPTEN_BINDINGS(order) { - value_tuple("OrderedTuple") - .element(&OrderedTuple::first) - .element(&OrderedTuple::second) - ; - - value_struct("OrderedStruct") - .field("first", &OrderedStruct::first) - .field("second", &OrderedStruct::second) - ; - - class_("SecondElement") - ; - - class_("FirstElement") - ; - - function("getOrderedTuple", &getOrderedTuple); - function("getOrderedStruct", &getOrderedStruct); -} - -// tests for unbound types - -template -T passThrough(T t) { - return t; -} - -struct UnboundClass { -}; - -struct HasUnboundBase : public UnboundClass { - static void noop() { - } -}; - -HasUnboundBase getHasUnboundBase(HasUnboundBase f) { - return f; -} - -struct HasConstructorUsingUnboundArgument { - HasConstructorUsingUnboundArgument(UnboundClass) { - } -}; - -struct SecondUnboundClass { -}; - -struct HasConstructorUsingUnboundArgumentAndUnboundBase : public SecondUnboundClass { - HasConstructorUsingUnboundArgumentAndUnboundBase(UnboundClass) { - } -}; - -struct BoundClass { - UnboundClass method(UnboundClass t) { - return t; - } - - static UnboundClass classfunction(UnboundClass t) { - return t; - } - - UnboundClass property; -}; - -EMSCRIPTEN_BINDINGS(incomplete) { - function("getUnboundClass", &passThrough); - - class_>("HasUnboundBase") - .class_function("noop", &HasUnboundBase::noop) - ; - function("getHasUnboundBase", &passThrough); - - class_("HasConstructorUsingUnboundArgument") - .constructor() - ; - - class_>("HasConstructorUsingUnboundArgumentAndUnboundBase") - .constructor() - ; - - class_("BoundClass") - .constructor<>() - .function("method", &BoundClass::method) - .class_function("classfunction", &BoundClass::classfunction) - .property("property", &BoundClass::property) - ; -} - -class Noncopyable { - Noncopyable(const Noncopyable&) = delete; - Noncopyable& operator=(const Noncopyable&) = delete; - -public: - Noncopyable() {} - Noncopyable(Noncopyable&& other) { - other.valid = false; - } - - std::string method() const { - return "foo"; - } - - bool valid = true; -}; - -Noncopyable getNoncopyable() { - return Noncopyable(); -} - -EMSCRIPTEN_BINDINGS(noncopyable) { - class_("Noncopyable") - .constructor<>() - .function("method", &Noncopyable::method) - ; - - function("getNoncopyable", &getNoncopyable); -} - -struct HasReadOnlyProperty { - HasReadOnlyProperty(int i) - : i(i) - {} - - const int i; -}; - -EMSCRIPTEN_BINDINGS(read_only_properties) { - class_("HasReadOnlyProperty") - .constructor() - .property("i", &HasReadOnlyProperty::i) - ; -} +#include +#include +#include +#include + +using namespace emscripten; + +val emval_test_mallinfo() { + const auto& i = mallinfo(); + val rv(val::object()); + rv.set("arena", val(i.arena)); + rv.set("ordblks", val(i.ordblks)); + rv.set("smblks", val(i.smblks)); + rv.set("hblks", val(i.hblks)); + rv.set("usmblks", val(i.usmblks)); + rv.set("fsmblks", val(i.fsmblks)); + rv.set("uordblks", val(i.uordblks)); + rv.set("fordblks", val(i.fordblks)); + rv.set("keepcost", val(i.keepcost)); + return rv; +} + +val emval_test_new_integer() { + return val(15); +} + +val emval_test_new_string() { + return val("Hello everyone"); +} + +std::string emval_test_get_string_from_val(val v) { + return v["key"].as(); +} + +val emval_test_new_object() { + val rv(val::object()); + rv.set("foo", val("bar")); + rv.set("baz", val(1)); + return rv; +} + +unsigned emval_test_passthrough_unsigned(unsigned v) { + return v; +} + +val emval_test_passthrough(val v) { + return v; +} + +void emval_test_return_void() { +} + +bool emval_test_not(bool b) { + return !b; +} + +unsigned emval_test_as_unsigned(val v) { + return v.as(); +} + +unsigned emval_test_get_length(val v) { + return v["length"].as(); +} + +double emval_test_add(char c, signed char sc, unsigned char uc, signed short ss, unsigned short us, signed int si, unsigned int ui, signed long sl, unsigned long ul, float f, double d) { + return c + sc + uc + ss + us + si + ui + sl + ul + f + d; +} + +float const_ref_adder(const int& i, const float& f) { + return i + f; +} + +unsigned emval_test_sum(val v) { + unsigned length = v["length"].as(); + double rv = 0; + for (unsigned i = 0; i < length; ++i) { + rv += v[i].as(); + } + return rv; +} + +std::string get_non_ascii_string() { + char c[128 + 1]; + c[128] = 0; + for (int i = 0; i < 128; ++i) { + c[i] = 128 + i; + } + return c; +} + +std::wstring get_non_ascii_wstring() { + std::wstring ws(4, 0); + ws[0] = 10; + ws[1] = 1234; + ws[2] = 2345; + ws[3] = 65535; + return ws; +} + +std::string emval_test_take_and_return_const_char_star(const char* str) { + return str; +} + +std::string emval_test_take_and_return_std_string(std::string str) { + return str; +} + +std::string emval_test_take_and_return_std_string_const_ref(const std::string& str) { + return str; +} + +std::wstring take_and_return_std_wstring(std::wstring str) { + return str; +} + +std::function emval_test_get_function_ptr() { + return emval_test_take_and_return_std_string; +} + +std::string emval_test_take_and_call_functor(std::function func) { + return func("asdf"); +} + +class ValHolder { +public: + ValHolder(val v) + : v_(v) + {} + + val getVal() const { + return v_; + } + + val getValNonConst() { + return v_; + } + + const val getConstVal() const { + return v_; + } + + const val& getValConstRef() const { + return v_; + } + + void setVal(val v) { + this->v_ = v; + } + + static int some_class_method(int i) { + return i; + } + + static const ValHolder* makeConst(val v) { + return new ValHolder(v); + } + + static ValHolder makeValHolder(val v) { + return ValHolder(v); + } + + static void set_via_raw_pointer(ValHolder* vh, val v) { + vh->setVal(v); + } + + static val get_via_raw_pointer(const ValHolder* vh) { + return vh->getVal(); + } + + static void transfer_via_raw_pointer(ValHolder* target, const ValHolder* source) { + target->setVal(source->getVal()); + } + + static val getValNonMember(const ValHolder& target) { + return target.getVal(); + } + +private: + val v_; +}; + +ValHolder emval_test_return_ValHolder() { + return val::object(); +} + +void emval_test_set_ValHolder_to_empty_object(ValHolder& vh) { + vh.setVal(val::object()); +} + +class StringHolder { +public: + StringHolder(const std::string& s) + : str_(s) + {} + + void set(const std::string& s) { + str_ = s; + } + + std::string get() const { + return str_; + } + + std::string& get_ref() { + return str_; + } + + const std::string& get_const_ref() const { + return str_; + } + +private: + std::string str_; +}; + +class SharedPtrHolder { +public: + SharedPtrHolder() + : ptr_(new StringHolder("a string")) + {} + + std::shared_ptr get() const { + return ptr_; + } + + void set(std::shared_ptr p) { + ptr_ = p; + } +private: + std::shared_ptr ptr_; +}; + +class VectorHolder { +public: + VectorHolder() { + v_.push_back(StringHolder("string #1")); + v_.push_back(StringHolder("string #2")); + } + + std::vector get() const { + return v_; + } + + void set(std::vector vec) { + v_ = vec; + } + +private: + std::vector v_; +}; + +class SmallClass { +public: + SmallClass(): member(7) {}; + int member; +}; + +class BigClass { +public: + BigClass(): member(11) {}; + int member; + int otherMember; + int yetAnotherMember; + + int getMember() { + return member; + } +}; + +class ParentClass { +public: + ParentClass(): bigClass() {}; + + BigClass bigClass; + + const BigClass& getBigClass() { + return bigClass; + }; +}; + +template +class TemplateClass { +public: + TemplateClass(T a, T b, T c) { + members[0] = a; + members[1] = b; + members[2] = c; + }; + + const T getMember(int n) { + return members[n]; + } + +protected: + T members[3]; +}; + +class ContainsTemplatedMemberClass { +public: + ContainsTemplatedMemberClass(): testTemplate(86, 87, 88) {}; + + TemplateClass testTemplate; + + const TemplateClass& getTestTemplate() { + return testTemplate; + }; +}; + +// Begin Inheritance Hierarchy Class Definitions + +class Base { +public: + Base(): name("Base"), + member(0), + baseMember(0) + {} + + std::string getClassName() const { + return name; + } + std::string getClassNameFromBase() const { + return name; + } + std::string getClassNameNotAvailableInDerivedClasses() { + // but wait -- if you act now we will throw in a SECOND base class method ABSOLUTELY FREE!! + return name; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + void setBaseMember(int value) { + baseMember = value; + } + int getBaseMember() { + return baseMember; + } + std::string name; + int member; + int baseMember; +}; + +class SecondBase { +public: + SecondBase() + : name("SecondBase"), + member(0), + secondBaseMember(0) + {} + + std::string getClassName() const { + return name; + } + std::string getClassNameNotAvailableInDerivedClasses() { + return name; + } + std::string getClassNameFromSecondBase() const { + return name; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + void setSecondBaseMember(int value) { + secondBaseMember = value; + } + int getSecondBaseMember() { + return secondBaseMember; + } + std::string name; + int member; + int secondBaseMember; +}; + +class Derived : public Base{ +public: + Derived() + : Base() + , member(0) + , name_("Derived") + {} + + std::string getClassName() const { + return name_; + } + void setMember(int value) { + member = value; + } + int getMember() { + return member; + } + int member; +private: + std::string name_; +}; + +class DerivedHolder { +public: + DerivedHolder() { + derived_.reset(); + } + void newDerived() { + deleteDerived(); + derived_ = std::shared_ptr(new Derived()); + } + void deleteDerived() { + derived_.reset(); + } + std::shared_ptr getDerived() { + return derived_; + } + std::string getDerivedClassName() { + return derived_->getClassName(); + } +private: + std::shared_ptr derived_; +}; + +class SiblingDerived : public Base { +public: + SiblingDerived() + : Base(), + name_("SiblingDerived") + {} + + std::string getClassName() const { + return name_; + } + +private: + std::string name_; +}; + +class MultiplyDerived : public Base, public SecondBase { +public: + MultiplyDerived() + : Base(), SecondBase(), + name_("MultiplyDerived") + { instanceCount_ ++; } + + ~MultiplyDerived() + { instanceCount_ --; } + + std::string getClassName() const { + return name_; + } + + static int getInstanceCount() { + return instanceCount_; + } +private: + std::string name_; + static int instanceCount_; +}; +int MultiplyDerived::instanceCount_ = 0; + +class DerivedTwice : public Derived { +public: + DerivedTwice() + : Derived(), + name_("DerivedTwice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedTwiceNotBound : public Derived { +public: + DerivedTwiceNotBound() + : Derived(), + name_("DerivedTwiceNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedThrice: public DerivedTwiceNotBound { +public: + DerivedThrice() + : DerivedTwiceNotBound(), + name_("DerivedThrice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class DerivedFourTimesNotBound: public DerivedThrice { +public: + DerivedFourTimesNotBound() + : DerivedThrice(), + name_("DerivedFourTimesNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyBase { +public: + PolyBase(const std::string& s) + : str_(s), + name_("PolyBase") + {} + + PolyBase(): name_("PolyBase") {} + + virtual ~PolyBase() {} + + virtual std::string virtualGetClassName() const { + return name_; + } + + std::string getClassName() const { + return name_; + } + +private: + std::string str_; + std::string name_; +}; + +class PolySecondBase { +public: + PolySecondBase(): name_("PolySecondBase") + {} + + virtual ~PolySecondBase() {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerived : public PolyBase{ +public: + PolyDerived() + : PolyBase("PolyDerived"), + name_("PolyDerived") + {} + + std::string virtualGetClassName() const { + return name_; + } + + std::string getClassName() const { + return name_; + } + + static void setPtrDerived() { + ptr_ = std::shared_ptr(new PolyDerived()); + } + + static void releasePtr() { + ptr_.reset(); + } + + static std::string getPtrClassName() { + return ptr_->getClassName(); + } + + static std::shared_ptr getPtr() { + return ptr_; + } + +private: + std::string name_; + static std::shared_ptr ptr_; +}; +std::shared_ptr PolyDerived::ptr_; + +class PolySiblingDerived : public PolyBase { +public: + PolySiblingDerived() + : PolyBase(), + name_("PolySiblingDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyMultiplyDerived : public PolyBase, public PolySecondBase { +public: + PolyMultiplyDerived() + : PolyBase(), PolySecondBase(), + name_("PolyMultiplyDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedTwiceWithoutSmartPointer: public PolyDerived { +public: + PolyDerivedTwiceWithoutSmartPointer() + : PolyDerived(), + name_("PolyDerivedTwiceWithoutSmartPointer") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedTwiceNotBound : public PolyDerived { +public: + PolyDerivedTwiceNotBound() + : PolyDerived(), + name_("PolyDerivedTwiceNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedThrice: public PolyDerivedTwiceNotBound { +public: + PolyDerivedThrice() + : PolyDerivedTwiceNotBound(), + name_("PolyDerivedThrice") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDerivedFourTimesNotBound: public PolyDerivedThrice { +public: + PolyDerivedFourTimesNotBound() + : PolyDerivedThrice(), + name_("PolyDerivedFourTimesNotBound") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondBase { +public: + PolyDiamondBase(): + name_("PolyBase") + {} + ~PolyDiamondBase() {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondDerived: public PolyDiamondBase { +public: + PolyDiamondDerived() + : PolyDiamondBase(), + name_("PolyDiamondDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondSiblingDerived: public PolyDiamondBase { +public: + PolyDiamondSiblingDerived() + : PolyDiamondBase(), + name_("PolyDiamondSiblingDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +class PolyDiamondMultiplyDerived: public PolyDiamondDerived, public PolyDiamondSiblingDerived { +public: + PolyDiamondMultiplyDerived() + : PolyDiamondDerived(), PolyDiamondSiblingDerived(), + name_("PolyDiamondMultiplyDerived") + {} + + std::string getClassName() const { + return name_; + } +private: + std::string name_; +}; + +// End Inheritance Hierarchy Class Definitions + +std::map embind_test_get_string_int_map() { + std::map m; + + m["one"] = 1; + m["two"] = 2; + + return m; +}; + +struct Vector { + Vector() = delete; + + Vector(float x_, float y_, float z_, float w_) + : x(x_) + , y(y_) + , z(z_) + , w(w_) + {} + + float x, y, z, w; + + float& operator[](int i) { + return (&x)[i]; + } + + const float& operator[](int i) const { + return (&x)[i]; + } + + float getY() const { + return y; + } + void setY(float _y) { + y = _y; + } +}; + +struct DummyDataToTestPointerAdjustment { + std::string dummy; +}; + +struct TupleVector : DummyDataToTestPointerAdjustment, Vector { + TupleVector(): Vector(0, 0, 0, 0) {} + TupleVector(float x, float y, float z, float w): Vector(x, y, z, w) {} +}; + +struct StructVector : DummyDataToTestPointerAdjustment, Vector { + StructVector(): Vector(0, 0, 0, 0) {} + StructVector(float x, float y, float z, float w): Vector(x, y, z, w) {} +}; + +float readVectorZ(const Vector& v) { + return v.z; +} + +void writeVectorZ(Vector& v, float z) { + v.z = z; +} + +struct TupleVectorTuple { + TupleVector v = TupleVector(0, 0, 0, 0); +}; + +TupleVector emval_test_return_TupleVector() { + return TupleVector(1, 2, 3, 4); +} + +TupleVector emval_test_take_and_return_TupleVector(TupleVector v) { + return v; +} + +TupleVectorTuple emval_test_return_TupleVectorTuple() { + TupleVectorTuple cvt; + cvt.v = emval_test_return_TupleVector(); + return cvt; +} + +StructVector emval_test_return_StructVector() { + return StructVector(1, 2, 3, 4); +} + +StructVector emval_test_take_and_return_StructVector(StructVector v) { + return v; +} + +struct CustomStruct { + CustomStruct() + : field(10) + {} + + const int& getField() const { + return field; + } + + int field; +}; + +struct TupleInStruct { + TupleVector field; +}; + +TupleInStruct emval_test_take_and_return_TupleInStruct(TupleInStruct cs) { + return cs; +} + +enum Enum { ONE, TWO }; + +Enum emval_test_take_and_return_Enum(Enum e) { + return e; +} + +enum class EnumClass { ONE, TWO }; + +EnumClass emval_test_take_and_return_EnumClass(EnumClass e) { + return e; +} + +void emval_test_call_function(val v, int i, float f, TupleVector tv, StructVector sv) { + v(i, f, tv, sv); +} + +std::unique_ptr emval_test_return_unique_ptr() { + return std::unique_ptr(new ValHolder(val::object())); +} + +std::shared_ptr emval_test_return_shared_ptr() { + return std::shared_ptr(new ValHolder(val::object())); +} + +std::shared_ptr emval_test_return_empty_shared_ptr() { + return std::shared_ptr(); +} + +bool emval_test_is_shared_ptr_null(std::shared_ptr p) { + return !p; +} + +static SmallClass smallClass; +static BigClass bigClass; + +SmallClass embind_test_return_small_class_instance() { + return smallClass; +} + +BigClass embind_test_return_big_class_instance() { + return bigClass; +} + +int embind_test_accept_small_class_instance(SmallClass c) { + return c.member; +} + +int embind_test_accept_big_class_instance(BigClass c) { + return c.member; +} + +// Begin Inheritance Hierarchy Test Wrappers + +Base* embind_test_return_raw_base_ptr() { + return new Base(); +} + +Base* embind_test_return_raw_derived_ptr_as_base() { + return new Derived(); +} + +Base* embind_test_return_raw_sibling_derived_ptr_as_base() { + return new SiblingDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_derived_ptr_as_base() { + return new PolyDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base() { + return new PolySiblingDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base() { + return new PolyMultiplyDerived(); +} + +PolySecondBase* embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base() { + return new PolyMultiplyDerived(); +} + +PolyBase* embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base() { + return new PolyDerivedFourTimesNotBound(); +} + +std::shared_ptr embind_test_return_smart_base_ptr() { + return std::shared_ptr(new Base()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_base_ptr() { + return std::shared_ptr(new PolyBase("PolyBase")); +} + +std::shared_ptr embind_test_return_smart_derived_ptr() { + return std::shared_ptr(new Derived()); +} + +std::shared_ptr embind_test_return_smart_sibling_derived_ptr() { + return std::shared_ptr(new SiblingDerived()); +} + +std::shared_ptr embind_test_return_smart_multiply_derived_ptr() { + return std::shared_ptr(new MultiplyDerived()); +} + +std::shared_ptr embind_test_return_smart_derived_thrice_ptr() { + return std::shared_ptr(new DerivedThrice()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr() { + return std::shared_ptr(new PolyDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr() { + return std::shared_ptr(new PolySiblingDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_multiply_derived_ptr() { + return std::shared_ptr(new PolyMultiplyDerived()); +} + +std::shared_ptr embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base() { + return std::shared_ptr(new PolyDerivedTwiceWithoutSmartPointer()); +} + +std::shared_ptr embind_test_return_smart_poly_derived_thrice_ptr() { + return std::shared_ptr(new PolyDerivedThrice()); +} + +std::shared_ptr embind_test_return_smart_derived_ptr_as_base() { + return std::shared_ptr(new PolyDerived()); +} + +val embind_test_return_smart_derived_ptr_as_val() { + return val(std::shared_ptr(new PolyDerived())); +} + +std::shared_ptr embind_test_return_smart_polymorphic_derived_ptr_as_base() { + return std::shared_ptr(new PolyDerived()); +} + +std::shared_ptr embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base() { + return std::shared_ptr(new PolySiblingDerived()); +} + +std::string embind_test_get_class_name_via_base_ptr(Base *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_second_base_ptr(SecondBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_polymorphic_base_ptr(PolyBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_polymorphic_second_base_ptr(PolySecondBase *p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_reference_to_smart_base_ptr(std::shared_ptr& p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_second_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +std::string embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(std::shared_ptr p) { + return p->virtualGetClassName(); +} + +std::string embind_test_get_class_name_via_smart_polymorphic_second_base_ptr(std::shared_ptr p) { + return p->getClassName(); +} + +void embind_modify_smart_pointer_passed_by_reference(std::shared_ptr& p) { + p = std::shared_ptr(new Base()); + p->name = "Changed"; +} + +void embind_attempt_to_modify_smart_pointer_when_passed_by_value(std::shared_ptr p) { + p = std::shared_ptr(new Base()); + p->name = "Changed"; +} + +static std::shared_ptr savedBasePointer; + +void embind_save_smart_base_pointer(std::shared_ptr p) { + savedBasePointer = p; +} + +// End Inheritance Hierarchy Test Wrappers + +std::vector emval_test_return_vector() { + int myints[] = { 10, 20, 30 }; + return std::vector(myints, myints + sizeof(myints) / sizeof(int)); +} + +std::vector > emval_test_return_vector_of_vectors() { + int myints1[] = { 10, 20, 30 }; + int myints2[] = { 40, 50, 60 }; + std::vector vec1(myints1, myints1 + sizeof(myints1) / sizeof(int)); + std::vector vec2(myints2, myints2 + sizeof(myints2) / sizeof(int)); + std::vector>vec3; + vec3.emplace_back(vec1); + vec3.emplace_back(vec2); + return vec3; +} + +std::vector> emval_test_return_shared_ptr_vector() { + std::vector> sharedStrVector; + sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #1"))); + sharedStrVector.push_back(std::shared_ptr(new StringHolder("string #2"))); + + return sharedStrVector; +} + +void test_string_with_vec(const std::string& p1, std::vector& v1) { + // THIS DOES NOT WORK -- need to get as val and then call vecFromJSArray + printf("%s\n", p1.c_str()); +} + +val embind_test_new_Object() { + return val::global("Object").new_(); +} + +val embind_test_new_factory(val factory, val argument) { + return factory.new_(10, std::string("hello"), argument); +} + +class AbstractClass { +public: + virtual ~AbstractClass() {} + virtual std::string abstractMethod() const = 0; + virtual std::string optionalMethod(std::string s) const { + return "optional" + s; + } +}; + +EMSCRIPTEN_SYMBOL(optionalMethod); + +class AbstractClassWrapper : public wrapper { +public: + EMSCRIPTEN_WRAPPER(AbstractClassWrapper); + + std::string abstractMethod() const { + return call("abstractMethod"); + } + std::string optionalMethod(std::string s) const { + return optional_call(optionalMethod_symbol, [&] { + return AbstractClass::optionalMethod(s); + }, s); + } +}; + +class ConcreteClass : public AbstractClass { + std::string abstractMethod() const { + return "from concrete"; + } +}; + +std::shared_ptr getAbstractClass() { + return std::make_shared(); +} + +std::string callAbstractMethod(AbstractClass& ac) { + return ac.abstractMethod(); +} + +std::string callOptionalMethod(AbstractClass& ac, std::string s) { + return ac.optionalMethod(s); +} + +class HasExternalConstructor { +public: + HasExternalConstructor(const std::string& str) + : m(str) + {} + + std::string getString() const { + return m; + } + + std::string m; +}; + +HasExternalConstructor* createHasExternalConstructor(const std::string& str) { + return new HasExternalConstructor(str); +} + +template +class CustomSmartPtr { +public: + CustomSmartPtr() + : CustomSmartPtr(nullptr) + { + std::fill(d_, d_ + N_, Valid); + } + + explicit CustomSmartPtr(T* t) + : ptr_(t) + { + std::fill(d_, d_ + N_, Valid); + } + + CustomSmartPtr(const CustomSmartPtr& other) + : ptr_(other.ptr_) + { + other.verify(); + std::fill(d_, d_ + N_, Valid); + if (ptr_) { + ++(ptr_->refcount); + } + } + + ~CustomSmartPtr() { + verify(); + std::fill(d_, d_ + N_, Deleted); + + if (ptr_ && --ptr_->refcount == 0) { + delete ptr_; + } + } + + T* get_raw() const { + return ptr_; + } + +private: + void verify() const { + for (size_t i = 0; i < N_; ++i) { + if (d_[i] != Valid) { + abort(); + } + } + } + + enum { + Valid = 255, + Deleted = 127, + }; + static constexpr size_t N_ = 1000000; + unsigned char d_[N_]; + T* ptr_; + + CustomSmartPtr& operator=(const CustomSmartPtr&) = delete; +}; + +class HeldBySmartPtr { +public: + HeldBySmartPtr(int i, const std::string& s) + : i(i) + , s(s) + {} + + static CustomSmartPtr newCustomPtr(int i, const std::string& s) { + return CustomSmartPtr(new HeldBySmartPtr(i, s)); + } + + int refcount = 1; + int i; + std::string s; +}; + +HeldBySmartPtr takesHeldBySmartPtr(HeldBySmartPtr p) { + return p; +} +std::shared_ptr takesHeldBySmartPtrSharedPtr(std::shared_ptr p) { + return p; +} + +namespace emscripten { + template + struct smart_ptr_trait> { + typedef T element_type; + + static sharing_policy get_sharing_policy() { + return sharing_policy::NONE; + } + + static T* get(const CustomSmartPtr& p) { + return p.get_raw(); + } + + static CustomSmartPtr share(const CustomSmartPtr& r, T* ptr) { + ++ptr->refcount; // implement an adopt API? + return CustomSmartPtr(ptr); + } + }; +} + +typedef CustomSmartPtr HeldByCustomSmartPtrPtr; + +class HeldByCustomSmartPtr { +public: + HeldByCustomSmartPtr(int i, const std::string& s) + : i(i) + , s(s) + {} + + static HeldByCustomSmartPtrPtr create(int i, const std::string& s) { + return HeldByCustomSmartPtrPtr(new HeldByCustomSmartPtr(i, s)); + } + + static std::shared_ptr createSharedPtr(int i, const std::string& s) { + return std::make_shared(i, s); + }; + + int refcount = 1; + int i; + std::string s; +}; + +HeldByCustomSmartPtr* passThroughRawPtr(HeldByCustomSmartPtr* p) { + return p; +} +HeldByCustomSmartPtrPtr passThroughCustomSmartPtr(HeldByCustomSmartPtrPtr p) { + return p; +} + +struct Base1 { +public: + Base1(): field1("Base1") {} + std::string field1; + + std::string getField() const { + return field1; + } +}; + +struct Base2 { +public: + Base2(): field2("Base2") {} + std::string field2; + + std::string getField() const { + return field2; + } +}; + +struct HasTwoBases : public Base1, public Base2 { +}; + +val get_module_property(const std::string& s) { + return val::module_property(s.c_str()); +} + +std::string char_to_string(char ch) { + char str[256]; + sprintf(str, "%d", (int)ch); + return str; +} + +std::string signed_char_to_string(signed char ch) { + char str[256]; + sprintf(str, "%hhd", ch); + return str; +} + +std::string unsigned_char_to_string(unsigned char ch) { + char str[256]; + sprintf(str, "%hhu", ch); + return str; +} + +std::string short_to_string(short val) { + char str[256]; + sprintf(str, "%hd", val); + return str; +} + +std::string unsigned_short_to_string(unsigned short val) { + char str[256]; + sprintf(str, "%hu", val); + return str; +} + +std::string int_to_string(int val) { + char str[256]; + sprintf(str, "%d", val); + return str; +} + +std::string unsigned_int_to_string(unsigned int val) { + char str[256]; + sprintf(str, "%u", val); + return str; +} + +std::string long_to_string(long val) { + char str[256]; + sprintf(str, "%ld", val); + return str; +} + +std::string unsigned_long_to_string(unsigned long val) { + char str[256]; + sprintf(str, "%lu", val); + return str; +} + +EMSCRIPTEN_BINDINGS(tests) { + register_vector("IntegerVector"); + register_vector("CharVector"); + register_vector("VectorUnsigned"); + register_vector("VectorUnsignedChar"); + register_vector("StringVector"); + register_vector("EmValVector"); + register_vector("FloatVector"); + register_vector>("IntegerVectorVector"); + + function("mallinfo", &emval_test_mallinfo); + function("emval_test_new_integer", &emval_test_new_integer); + function("emval_test_new_string", &emval_test_new_string); + function("emval_test_get_string_from_val", &emval_test_get_string_from_val); + function("emval_test_new_object", &emval_test_new_object); + function("emval_test_passthrough_unsigned", &emval_test_passthrough_unsigned); + function("emval_test_passthrough", &emval_test_passthrough); + function("emval_test_return_void", &emval_test_return_void); + function("emval_test_not", &emval_test_not); + + function("emval_test_as_unsigned", &emval_test_as_unsigned); + function("emval_test_get_length", &emval_test_get_length); + function("emval_test_add", &emval_test_add); + function("const_ref_adder", &const_ref_adder); + function("emval_test_sum", &emval_test_sum); + + function("get_non_ascii_string", &get_non_ascii_string); + function("get_non_ascii_wstring", &get_non_ascii_wstring); + //function("emval_test_take_and_return_const_char_star", &emval_test_take_and_return_const_char_star); + function("emval_test_take_and_return_std_string", &emval_test_take_and_return_std_string); + function("emval_test_take_and_return_std_string_const_ref", &emval_test_take_and_return_std_string_const_ref); + function("take_and_return_std_wstring", &take_and_return_std_wstring); + + //function("emval_test_take_and_return_CustomStruct", &emval_test_take_and_return_CustomStruct); + + value_tuple("TupleVector") + .element(&TupleVector::x) + .element(&Vector::getY, &Vector::setY) + .element(&readVectorZ, &writeVectorZ) + .element(index<3>()) + ; + + function("emval_test_return_TupleVector", &emval_test_return_TupleVector); + function("emval_test_take_and_return_TupleVector", &emval_test_take_and_return_TupleVector); + + value_tuple("TupleVectorTuple") + .element(&TupleVectorTuple::v) + ; + + function("emval_test_return_TupleVectorTuple", &emval_test_return_TupleVectorTuple); + + value_struct("StructVector") + .field("x", &StructVector::x) + .field("y", &Vector::getY, &Vector::setY) + .field("z", &readVectorZ, &writeVectorZ) + .field("w", index<3>()) + ; + + function("emval_test_return_StructVector", &emval_test_return_StructVector); + function("emval_test_take_and_return_StructVector", &emval_test_take_and_return_StructVector); + + value_struct("TupleInStruct") + .field("field", &TupleInStruct::field) + ; + + function("emval_test_take_and_return_TupleInStruct", &emval_test_take_and_return_TupleInStruct); + + class_("ValHolder") + .smart_ptr>() + .constructor() + .function("getVal", &ValHolder::getVal) + .function("getValNonConst", &ValHolder::getValNonConst) + .function("getConstVal", &ValHolder::getConstVal) + .function("getValConstRef", &ValHolder::getValConstRef) + .function("setVal", &ValHolder::setVal) + .property("val", &ValHolder::getVal, &ValHolder::setVal) + .property("val_readonly", &ValHolder::getVal) + .class_function("makeConst", &ValHolder::makeConst, allow_raw_pointer()) + .class_function("makeValHolder", &ValHolder::makeValHolder) + .class_function("some_class_method", &ValHolder::some_class_method) + .class_function("set_via_raw_pointer", + &ValHolder::set_via_raw_pointer, + allow_raw_pointer>()) + .class_function("get_via_raw_pointer", + &ValHolder::get_via_raw_pointer, + allow_raw_pointer>()) + .class_function("transfer_via_raw_pointer", + &ValHolder::transfer_via_raw_pointer, + allow_raw_pointers()) + + // non-member method + .function("setEmpty", &emval_test_set_ValHolder_to_empty_object) + .function("getValNonMember", &ValHolder::getValNonMember) + ; + + function("emval_test_return_ValHolder", &emval_test_return_ValHolder); + function("emval_test_set_ValHolder_to_empty_object", &emval_test_set_ValHolder_to_empty_object); + + class_>("StringFunctorString") + .constructor<>() + .function("opcall", &std::function::operator()) + ; + + function("emval_test_get_function_ptr", &emval_test_get_function_ptr); + function("emval_test_take_and_call_functor", &emval_test_take_and_call_functor); + + class_("StringHolder") + .smart_ptr>() + .constructor() + .function("set", &StringHolder::set) + .function("get", &StringHolder::get) + .function("get_const_ref", &StringHolder::get_const_ref) + ; + + class_("SharedPtrHolder") + .constructor<>() + .function("get", &SharedPtrHolder::get) + .function("set", &SharedPtrHolder::set) + ; + + class_("SmallClass") + .constructor<>() + .property("member", &SmallClass::member) + ; + + class_("BigClass") + .constructor<>() + .property("member", &BigClass::member) + .property("otherMember", &BigClass::otherMember) + .property("yetAnotherMember", &BigClass::yetAnotherMember) + .function("getMember", &BigClass::getMember) + ; + + class_("ParentClass") + .constructor<>() + .function("getBigClass", &ParentClass::getBigClass) + ; + + class_>("IntTemplateClass") + .constructor() + .function("getMember", &TemplateClass::getMember) + ; + + class_("ContainsTemplatedMemberClass") + .constructor<>() + .function("getTestTemplate", &ContainsTemplatedMemberClass::getTestTemplate) + ; + + // register Derived before Base as a test that it's possible to + // register base classes afterwards + class_>("Derived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &Derived::getClassName) + .function("getMember", &Derived::getMember) + .function("setMember", &Derived::setMember) + .property("member", &Derived::member) + ; + + class_("Base") + .smart_ptr>() + .constructor<>() + .function("getClassName", &Base::getClassName) + .function("getClassNameFromBase", &Base::getClassNameFromBase) + .function("getClassNameNotAvailableInDerivedClasses", &Base::getClassNameNotAvailableInDerivedClasses) + .function("getMember", &Base::getMember) + .function("setMember", &Base::setMember) + .function("getBaseMember", &Base::getBaseMember) + .function("setBaseMember", &Base::setBaseMember) + .property("member", &Base::member) + .property("baseMember", &Base::baseMember) + ; + + class_("SecondBase") + .smart_ptr>() + .constructor<>() + .function("getClassName", &SecondBase::getClassName) + .function("getClassNameFromSecondBase", &SecondBase::getClassNameFromSecondBase) + .function("getClassNameNotAvailableInDerivedClasses", &SecondBase::getClassNameNotAvailableInDerivedClasses) + .function("getMember", &SecondBase::getMember) + .function("setMember", &SecondBase::setMember) + .function("getSecondBaseMember", &SecondBase::getSecondBaseMember) + .function("setSecondBaseMember", &SecondBase::setSecondBaseMember) + .property("member", &SecondBase::member) + .property("secondBaseMember", &SecondBase::secondBaseMember) + ; + + + class_("DerivedHolder") + .constructor<>() + .function("newDerived", &DerivedHolder::newDerived) + .function("deleteDerived", &DerivedHolder::deleteDerived) + .function("getDerived", &DerivedHolder::getDerived) + .function("getDerivedClassName", &DerivedHolder::getDerivedClassName) + ; + + class_("SiblingDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &SiblingDerived::getClassName) + ; + + class_>("MultiplyDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &MultiplyDerived::getClassName) + .class_function("getInstanceCount", &MultiplyDerived::getInstanceCount) + ; + + class_ >("DerivedTwice") + .constructor<>() + .function("getClassName", &DerivedTwice::getClassName) + ; + + class_ >("DerivedThrice") + .smart_ptr>() + .constructor<>() + .function("getClassName", &DerivedThrice::getClassName) + ; + + class_("PolyBase") + .smart_ptr>() + .constructor<>() + .function("virtualGetClassName", &PolyBase::virtualGetClassName) + .function("getClassName", &PolyBase::getClassName) + ; + + class_("PolySecondBase") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolySecondBase::getClassName) + ; + + class_>("PolyDerived") + .smart_ptr>() + .constructor<>() + .function("virtualGetClassName", &PolyDerived::virtualGetClassName) + .function("getClassName", &PolyDerived::getClassName) + .class_function("setPtrDerived", &PolyDerived::setPtrDerived) + .class_function("releasePtr", &PolyDerived::releasePtr) + .class_function("getPtrClassName", &PolyDerived::getPtrClassName) + .class_function("getPtr", &PolyDerived::getPtr) + ; +// static void setPtrDerived() { +// ptr = std::shared_ptr(new PolyDerived()); +// } +// +// static std::string getPtrClassName() { +// return ptr->getClassName(); +// } +// +// static std::shared_ptr getPtr() { +// return ptr; +// } + + class_>("PolySiblingDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolySiblingDerived::getClassName) + ; + + class_>("PolyMultiplyDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyMultiplyDerived::getClassName) + ; + + class_>("PolyDerivedThrice") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyDerivedThrice::getClassName) + ; + + class_("PolyDiamondBase") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyDiamondBase::getClassName) + ; + + class_("PolyDiamondDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyDiamondDerived::getClassName) + ; + + class_("PolyDiamondSiblingDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyDiamondSiblingDerived::getClassName) + ; + + class_("PolyDiamondMultiplyDerived") + .smart_ptr>() + .constructor<>() + .function("getClassName", &PolyDiamondMultiplyDerived::getClassName) + ; + + function("embind_test_return_small_class_instance", &embind_test_return_small_class_instance); + function("embind_test_return_big_class_instance", &embind_test_return_big_class_instance); + function("embind_test_accept_small_class_instance", &embind_test_accept_small_class_instance); + function("embind_test_accept_big_class_instance", &embind_test_accept_big_class_instance); + + function("embind_test_return_raw_base_ptr", embind_test_return_raw_base_ptr, allow_raw_pointer()); + function("embind_test_return_raw_derived_ptr_as_base", embind_test_return_raw_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_sibling_derived_ptr_as_base", embind_test_return_raw_sibling_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_derived_ptr_as_base", embind_test_return_raw_polymorphic_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base", embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base", embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base, allow_raw_pointer()); + function("embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base", embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base, allow_raw_pointer()); + function("embind_test_return_smart_derived_ptr", embind_test_return_smart_derived_ptr); + function("embind_test_return_smart_sibling_derived_ptr", embind_test_return_smart_sibling_derived_ptr); + function("embind_test_return_smart_multiply_derived_ptr", embind_test_return_smart_multiply_derived_ptr); + function("embind_test_return_smart_derived_thrice_ptr", embind_test_return_smart_derived_thrice_ptr); + function("embind_test_return_smart_base_ptr", embind_test_return_smart_base_ptr); + function("embind_test_return_smart_polymorphic_base_ptr", embind_test_return_smart_polymorphic_base_ptr); + function("embind_test_return_smart_polymorphic_derived_ptr", embind_test_return_smart_polymorphic_derived_ptr); + function("embind_test_return_smart_polymorphic_sibling_derived_ptr", embind_test_return_smart_polymorphic_sibling_derived_ptr); + function("embind_test_return_smart_polymorphic_multiply_derived_ptr", embind_test_return_smart_polymorphic_multiply_derived_ptr); + function("embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base", embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base); + function("embind_test_return_smart_poly_derived_thrice_ptr", embind_test_return_smart_poly_derived_thrice_ptr); + function("embind_test_return_smart_derived_ptr_as_base", embind_test_return_smart_derived_ptr_as_base); + function("embind_test_return_smart_derived_ptr_as_val", embind_test_return_smart_derived_ptr_as_val); + function("embind_test_return_smart_polymorphic_derived_ptr_as_base", embind_test_return_smart_polymorphic_derived_ptr_as_base); + function("embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base", embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base); + function("embind_test_get_class_name_via_base_ptr", embind_test_get_class_name_via_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_second_base_ptr", embind_test_get_class_name_via_second_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_polymorphic_base_ptr", embind_test_get_class_name_via_polymorphic_base_ptr, allow_raw_pointer>()); + function("embind_test_get_class_name_via_polymorphic_second_base_ptr", embind_test_get_class_name_via_polymorphic_second_base_ptr, allow_raw_pointer>()); + // todo: allow_raw_pointer should fail earlier if argument is not a pointer + function("embind_test_get_class_name_via_smart_base_ptr", embind_test_get_class_name_via_smart_base_ptr); + function("embind_test_get_class_name_via_reference_to_smart_base_ptr", embind_test_get_class_name_via_reference_to_smart_base_ptr); + function("embind_test_get_class_name_via_smart_second_base_ptr", embind_test_get_class_name_via_smart_second_base_ptr); + function("embind_test_get_class_name_via_smart_polymorphic_base_ptr", embind_test_get_class_name_via_smart_polymorphic_base_ptr); + function("embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr", embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr); + function("embind_test_get_class_name_via_smart_polymorphic_second_base_ptr", embind_test_get_class_name_via_smart_polymorphic_second_base_ptr); + function("embind_modify_smart_pointer_passed_by_reference", embind_modify_smart_pointer_passed_by_reference); + function("embind_attempt_to_modify_smart_pointer_when_passed_by_value", embind_attempt_to_modify_smart_pointer_when_passed_by_value); + function("embind_save_smart_base_pointer", embind_save_smart_base_pointer); + + class_("Base1") + .constructor() + .function("getField", &Base1::getField) + ; + + class_("Base2") + .function("getField", &Base2::getField) + .property("field", &Base2::field2) + ; + + class_>("HasTwoBases") + .constructor() + ; + + class_("CustomStruct") + .constructor<>() + .property("field", &CustomStruct::field) + .function("getField", &CustomStruct::getField) + ; + + enum_("Enum") + .value("ONE", ONE) + .value("TWO", TWO) + ; + function("emval_test_take_and_return_Enum", &emval_test_take_and_return_Enum); + + enum_("EnumClass") + .value("ONE", EnumClass::ONE) + .value("TWO", EnumClass::TWO) + ; + function("emval_test_take_and_return_EnumClass", &emval_test_take_and_return_EnumClass); + + function("emval_test_call_function", &emval_test_call_function); + + function("emval_test_return_unique_ptr", &emval_test_return_unique_ptr); + + function("emval_test_return_shared_ptr", &emval_test_return_shared_ptr); + function("emval_test_return_empty_shared_ptr", &emval_test_return_empty_shared_ptr); + function("emval_test_is_shared_ptr_null", &emval_test_is_shared_ptr_null); + + function("emval_test_return_vector", &emval_test_return_vector); + function("emval_test_return_vector_of_vectors", &emval_test_return_vector_of_vectors); + + register_vector>("SharedPtrVector"); + function("emval_test_return_shared_ptr_vector", &emval_test_return_shared_ptr_vector); + + function("get_module_property", &get_module_property); + + register_vector("StringHolderVector"); + class_("VectorHolder") + .constructor<>() + .function("get", &VectorHolder::get) + .function("set", &VectorHolder::set) + ; + + function("test_string_with_vec", &test_string_with_vec); + + register_map("StringIntMap"); + function("embind_test_get_string_int_map", embind_test_get_string_int_map); + + function("embind_test_new_Object", &embind_test_new_Object); + function("embind_test_new_factory", &embind_test_new_factory); + + class_("AbstractClass") + .smart_ptr>() + .allow_subclass() + .function("abstractMethod", &AbstractClass::abstractMethod) + .function("optionalMethod", &AbstractClass::optionalMethod) + ; + + function("getAbstractClass", &getAbstractClass); + function("callAbstractMethod", &callAbstractMethod); + function("callOptionalMethod", &callOptionalMethod); + + class_("HasExternalConstructor") + .constructor(&createHasExternalConstructor) + .function("getString", &HasExternalConstructor::getString) + ; + + auto HeldBySmartPtr_class = class_("HeldBySmartPtr"); + HeldBySmartPtr_class + .smart_ptr>() + .smart_ptr_constructor(&std::make_shared) + .class_function("newCustomPtr", HeldBySmartPtr::newCustomPtr) + .function("returnThis", &takesHeldBySmartPtrSharedPtr) + .property("i", &HeldBySmartPtr::i) + .property("s", &HeldBySmartPtr::s) + ; + function("takesHeldBySmartPtr", &takesHeldBySmartPtr); + function("takesHeldBySmartPtrSharedPtr", &takesHeldBySmartPtrSharedPtr); + + class_("HeldByCustomSmartPtr") + .smart_ptr>() + .smart_ptr_constructor(&HeldByCustomSmartPtr::create) + .class_function("createSharedPtr", &HeldByCustomSmartPtr::createSharedPtr) + .property("i", &HeldByCustomSmartPtr::i) + .property("s", &HeldByCustomSmartPtr::s) + ; + + function("passThroughRawPtr", &passThroughRawPtr, allow_raw_pointers()); + function("passThroughCustomSmartPtr", &passThroughCustomSmartPtr); + + function("char_to_string", &char_to_string); + function("signed_char_to_string", &signed_char_to_string); + function("unsigned_char_to_string", &unsigned_char_to_string); + function("short_to_string", &short_to_string); + function("unsigned_short_to_string", &unsigned_short_to_string); + function("int_to_string", &int_to_string); + function("unsigned_int_to_string", &unsigned_int_to_string); + function("long_to_string", &long_to_string); + function("unsigned_long_to_string", &unsigned_long_to_string); +} + +int overloaded_function(int i) { + assert(i == 10); + return 1; +} + +int overloaded_function(int i, int j) { + assert(i == 20); + assert(j == 20); + return 2; +} + +class MultipleCtors { +public: + int value; + + MultipleCtors(int i) { + value = 1; + assert(i == 10); + } + MultipleCtors(int i, int j) { + value = 2; + assert(i == 20); + assert(j == 20); + } + MultipleCtors(int i, int j, int k) { + value = 3; + assert(i == 30); + assert(j == 30); + assert(k == 30); + } + + int WhichCtorCalled() const { + return value; + } +}; + +class MultipleOverloads { +public: + MultipleOverloads() {} + + int value; + static int staticValue; + + int Func(int i) { + assert(i == 10); + value = 1; + return 1; + } + int Func(int i, int j) { + assert(i == 20); + assert(j == 20); + value = 2; + return 2; + } + + int WhichFuncCalled() const { + return value; + } + + static int StaticFunc(int i) { + assert(i == 10); + staticValue = 1; + return 1; + } + static int StaticFunc(int i, int j) { + assert(i == 20); + assert(j == 20); + staticValue = 2; + return 2; + } + + static int WhichStaticFuncCalled() { + return staticValue; + } +}; + +class MultipleOverloadsDerived : public MultipleOverloads { +public: + MultipleOverloadsDerived() {} + + int Func(int i, int j, int k) { + assert(i == 30); + assert(j == 30); + assert(k == 30); + value = 3; + return 3; + } + int Func(int i, int j, int k, int l) { + assert(i == 40); + assert(j == 40); + assert(k == 40); + assert(l == 40); + value = 4; + return 4; + } + + static int StaticFunc(int i, int j, int k) { + assert(i == 30); + assert(j == 30); + assert(k == 30); + staticValue = 3; + return 3; + } + static int StaticFunc(int i, int j, int k, int l) { + assert(i == 40); + assert(j == 40); + assert(k == 40); + assert(l == 40); + staticValue = 4; + return 4; + } +}; + +struct MultipleAccessors { + int getConst() { + return 1; + } + int getConst() const { + return 2; + } + int getConst(int i) const { + return i; + } +}; + +struct ConstAndNonConst { + void method(int) { + } + + int method() const { + return 10; + } +}; + +EMSCRIPTEN_BINDINGS(overloads) { + function("overloaded_function", select_overload(&overloaded_function)); + function("overloaded_function", select_overload(&overloaded_function)); + + class_("MultipleCtors") + .constructor() + .constructor() + .constructor() + .function("WhichCtorCalled", &MultipleCtors::WhichCtorCalled); + + class_("MultipleOverloads") + .constructor<>() + .function("Func", select_overload(&MultipleOverloads::Func)) + .function("Func", select_overload(&MultipleOverloads::Func)) + .function("WhichFuncCalled", &MultipleOverloads::WhichFuncCalled) + .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) + .class_function("StaticFunc", select_overload(&MultipleOverloads::StaticFunc)) + .class_function("WhichStaticFuncCalled", &MultipleOverloads::WhichStaticFuncCalled) + ; + + class_ >("MultipleOverloadsDerived") + .constructor<>() + .function("Func", select_overload(&MultipleOverloadsDerived::Func)) + .function("Func", select_overload(&MultipleOverloadsDerived::Func)) + .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) + .class_function("StaticFunc", select_overload(&MultipleOverloadsDerived::StaticFunc)) + ; + + class_("MultipleAccessors") + .function("getConst", select_overload(&MultipleAccessors::getConst)) + ; + + class_("ConstAndNonConst") + .function("method", select_const(&ConstAndNonConst::method)) + ; +} + +// tests for out-of-order registration + +class SecondElement { +}; + +class FirstElement { +}; + +struct OrderedTuple { + FirstElement first; + SecondElement second; +}; + +struct OrderedStruct { + FirstElement first; + SecondElement second; +}; + +OrderedTuple getOrderedTuple() { + return OrderedTuple(); +} + +OrderedStruct getOrderedStruct() { + return OrderedStruct(); +} + +EMSCRIPTEN_BINDINGS(order) { + value_tuple("OrderedTuple") + .element(&OrderedTuple::first) + .element(&OrderedTuple::second) + ; + + value_struct("OrderedStruct") + .field("first", &OrderedStruct::first) + .field("second", &OrderedStruct::second) + ; + + class_("SecondElement") + ; + + class_("FirstElement") + ; + + function("getOrderedTuple", &getOrderedTuple); + function("getOrderedStruct", &getOrderedStruct); +} + +// tests for unbound types + +template +T passThrough(T t) { + return t; +} + +struct UnboundClass { +}; + +struct HasUnboundBase : public UnboundClass { + static void noop() { + } +}; + +HasUnboundBase getHasUnboundBase(HasUnboundBase f) { + return f; +} + +struct HasConstructorUsingUnboundArgument { + HasConstructorUsingUnboundArgument(UnboundClass) { + } +}; + +struct SecondUnboundClass { +}; + +struct HasConstructorUsingUnboundArgumentAndUnboundBase : public SecondUnboundClass { + HasConstructorUsingUnboundArgumentAndUnboundBase(UnboundClass) { + } +}; + +struct BoundClass { + UnboundClass method(UnboundClass t) { + return t; + } + + static UnboundClass classfunction(UnboundClass t) { + return t; + } + + UnboundClass property; +}; + +EMSCRIPTEN_BINDINGS(incomplete) { + function("getUnboundClass", &passThrough); + + class_>("HasUnboundBase") + .class_function("noop", &HasUnboundBase::noop) + ; + function("getHasUnboundBase", &passThrough); + + class_("HasConstructorUsingUnboundArgument") + .constructor() + ; + + class_>("HasConstructorUsingUnboundArgumentAndUnboundBase") + .constructor() + ; + + class_("BoundClass") + .constructor<>() + .function("method", &BoundClass::method) + .class_function("classfunction", &BoundClass::classfunction) + .property("property", &BoundClass::property) + ; +} + +class Noncopyable { + Noncopyable(const Noncopyable&) = delete; + Noncopyable& operator=(const Noncopyable&) = delete; + +public: + Noncopyable() {} + Noncopyable(Noncopyable&& other) { + other.valid = false; + } + + std::string method() const { + return "foo"; + } + + bool valid = true; +}; + +Noncopyable getNoncopyable() { + return Noncopyable(); +} + +EMSCRIPTEN_BINDINGS(noncopyable) { + class_("Noncopyable") + .constructor<>() + .function("method", &Noncopyable::method) + ; + + function("getNoncopyable", &getNoncopyable); +} + +struct HasReadOnlyProperty { + HasReadOnlyProperty(int i) + : i(i) + {} + + const int i; +}; + +EMSCRIPTEN_BINDINGS(read_only_properties) { + class_("HasReadOnlyProperty") + .constructor() + .property("i", &HasReadOnlyProperty::i) + ; +} + +EMSCRIPTEN_BINDINGS(constants) { + constant("INT_CONSTANT", 10); + constant("STRING_CONSTANT", std::string("some string")); + + TupleVector tv(1, 2, 3, 4); + constant("VALUE_TUPLE_CONSTANT", tv); + + StructVector sv(1, 2, 3, 4); + constant("VALUE_STRUCT_CONSTANT", sv); +} From 9e375f0d243fbd21289283d2f61836ddfc4983c2 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Tue, 23 Apr 2013 18:23:11 -0700 Subject: [PATCH 03/39] snip dead code --- system/include/emscripten/bind.h | 68 -------------------------------- 1 file changed, 68 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index d5b2fe6a49b0f..ff7feacf92451 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -1233,74 +1233,6 @@ namespace emscripten { TypeID::get(), asGenericValue(BindingType::toWireType(v))); } - - namespace internal { - template - class optional { - public: - optional() - : initialized(false) - {} - - ~optional() { - if (initialized) { - get()->~T(); - } - } - - 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; - } - - optional& operator=(const T& v) { - if (initialized) { - get()->~T(); - } - new(get()) T(v); - 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(&data); - } - - T const* get() const { - return reinterpret_cast(&data); - } - - bool initialized; - typename std::aligned_storage::type data; - }; - } } namespace emscripten { From 2dc3ce9992a96ae80013e7ee24ba78ce777c97f1 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Wed, 24 Apr 2013 15:10:10 -0700 Subject: [PATCH 04/39] namespace the binding struct a bit more --- system/include/emscripten/bind.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index ff7feacf92451..5e87bd69d4e94 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -1248,7 +1248,7 @@ namespace emscripten { } #define EMSCRIPTEN_BINDINGS(name) \ - static struct BindingInitializer_##name { \ - BindingInitializer_##name(); \ - } BindingInitializer_##name##_instance; \ - BindingInitializer_##name::BindingInitializer_##name() + static struct EmscriptenBindingInitializer_##name { \ + EmscriptenBindingInitializer_##name(); \ + } EmscriptenBindingInitializer_##name##_instance; \ + EmscriptenBindingInitializer_##name::EmscriptenBindingInitializer_##name() From 9b2cb58a355d4645fe2c7352a0408dc43e99d538 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 25 Apr 2013 01:49:52 -0700 Subject: [PATCH 05/39] Snip some dead code --- system/include/emscripten/bind.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 5e87bd69d4e94..7aa2a55e9b701 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -1235,18 +1235,6 @@ namespace emscripten { } } -namespace emscripten { - namespace internal { - class BindingsDefinition { - public: - template - BindingsDefinition(Function fn) { - fn(); - } - }; - } -} - #define EMSCRIPTEN_BINDINGS(name) \ static struct EmscriptenBindingInitializer_##name { \ EmscriptenBindingInitializer_##name(); \ From 54526667562b394f1c3673a48780b18000d798a6 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Mon, 29 Apr 2013 18:29:43 -0700 Subject: [PATCH 06/39] checkpoint object handle composition --- src/embind/embind.js | 10 ++++++++++ tests/embind/embind.test.js | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/embind/embind.js b/src/embind/embind.js index 988526b4853bd..78f54e31ea37d 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1054,6 +1054,16 @@ function getInstanceTypeName(handle) { return handle.$$.ptrType.registeredClass.name; } +ClassHandle.prototype.isAliasOf = function(other) { + if (!(this instanceof ClassHandle)) { + return false; + } + if (!(other instanceof ClassHandle)) { + return false; + } + return this.$$.ptr == other.$$.ptr; +} + ClassHandle.prototype.clone = function() { if (!this.$$.ptr) { throwBindingError(getInstanceTypeName(this) + ' instance already deleted'); diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 8ef46ad8f9c72..812c3b8b609f7 100755 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1682,6 +1682,26 @@ module({ assert.deepEqual([1, 2, 3, 4], cm.VALUE_TUPLE_CONSTANT); assert.deepEqual({x:1,y:2,z:3,w:4}, cm.VALUE_STRUCT_CONSTANT); }); + + BaseFixture.extend("object handle comparison", function() { + var e = new cm.ValHolder("foo"); + var f = new cm.ValHolder("foo"); + assert.false(e.isAliasOf(undefined)); + assert.false(e.isAliasOf(10)); + assert.true(e.isAliasOf(e)); + assert.false(e.isAliasOf(f)); + assert.false(f.isAliasOf(e)); + e.delete(); + f.delete(); + }); + + BaseFixture.extend("smart pointers compare with raw", function() { + // todo + }); + + BaseFixture.extend("derived-with-offset types compare with base", function() { + // todo + }); }); /* global run_all_tests */ From 9607e5be25f12ac986436622bdd3b710505a596c Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Tue, 30 Apr 2013 15:01:08 -0700 Subject: [PATCH 07/39] Add isAliasOf for seeing if two embind handles point to the same underlying object. Conflicts: tests/embind/embind_test.cpp --- src/embind/embind.js | 20 ++++++++++++++++++-- tests/embind/embind.test.js | 11 ++++++----- tests/embind/embind_test.cpp | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/embind/embind.js b/src/embind/embind.js index 78f54e31ea37d..cadee700ec419 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1061,8 +1061,24 @@ ClassHandle.prototype.isAliasOf = function(other) { if (!(other instanceof ClassHandle)) { return false; } - return this.$$.ptr == other.$$.ptr; -} + + var leftClass = this.$$.ptrType.registeredClass; + var left = this.$$.ptr; + var rightClass = other.$$.ptrType.registeredClass; + var right = other.$$.ptr; + + while (leftClass.baseClass) { + left = leftClass.upcast(left); + leftClass = leftClass.baseClass; + } + + while (rightClass.baseClass) { + right = rightClass.upcast(right); + rightClass = rightClass.baseClass; + } + + return leftClass === rightClass && left === right; +}; ClassHandle.prototype.clone = function() { if (!this.$$.ptr) { diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 812c3b8b609f7..2f407471d9324 100755 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1695,12 +1695,13 @@ module({ f.delete(); }); - BaseFixture.extend("smart pointers compare with raw", function() { - // todo - }); - BaseFixture.extend("derived-with-offset types compare with base", function() { - // todo + var e = new cm.DerivedWithOffset; + var f = cm.return_Base_from_DerivedWithOffset(e); + assert.true(e.isAliasOf(f)); + assert.true(f.isAliasOf(e)); + e.delete(); + f.delete(); }); }); diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index 48da45b8a5e6b..21fbee656cfe3 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -2141,3 +2141,18 @@ EMSCRIPTEN_BINDINGS(constants) { StructVector sv(1, 2, 3, 4); constant("VALUE_STRUCT_CONSTANT", sv); } + +class DerivedWithOffset : public DummyDataToTestPointerAdjustment, public Base { +}; + +std::shared_ptr return_Base_from_DerivedWithOffset(std::shared_ptr ptr) { + return ptr; +} + +EMSCRIPTEN_BINDINGS(with_adjustment) { + class_>("DerivedWithOffset") + .smart_ptr_constructor(&std::make_shared) + ; + + function("return_Base_from_DerivedWithOffset", &return_Base_from_DerivedWithOffset); +} From 58352074e51c15bd108a71a3c31354206d488eee Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 2 May 2013 00:01:08 -0700 Subject: [PATCH 08/39] Add a benchmark for calling from C++ into JS via interfaces --- emscripten.py | 1 + system/include/emscripten/val.h | 1 + tests/embind/build_benchmark | 2 + tests/embind/embind.benchmark.js | 26 +++++++++++ tests/embind/embind_benchmark.cpp | 71 +++++++++++++++++++++++++++++-- 5 files changed, 98 insertions(+), 3 deletions(-) create mode 100755 tests/embind/build_benchmark diff --git a/emscripten.py b/emscripten.py index f4bfed8294073..924012af6bdf8 100755 --- a/emscripten.py +++ b/emscripten.py @@ -767,6 +767,7 @@ def _main(environ): if keywords.temp_dir is None: temp_files = get_configuration().get_temp_files() + temp_dir = get_configuration().TEMP_DIR else: temp_dir = os.path.abspath(keywords.temp_dir) if not os.path.exists(temp_dir): diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index 09cad80e1daeb..edd070e3418ad 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -10,6 +10,7 @@ namespace emscripten { extern "C" { void _emval_register_symbol(const char*); + typedef struct _EM_SIG* EM_SIG; typedef struct _EM_VAL* EM_VAL; void _emval_incref(EM_VAL value); diff --git a/tests/embind/build_benchmark b/tests/embind/build_benchmark new file mode 100755 index 0000000000000..f878a2d409d9e --- /dev/null +++ b/tests/embind/build_benchmark @@ -0,0 +1,2 @@ +#!/bin/bash +EMCC_LLVM_TARGET=le32-unknown-nacl ~/projects/emscripten/emcc --minify 0 --bind --pre-js embind.benchmark.js -O2 --shell-file shell.html -o embind_benchmark.html embind_benchmark.cpp diff --git a/tests/embind/embind.benchmark.js b/tests/embind/embind.benchmark.js index fcbd64ef052a8..7b20db8876a14 100644 --- a/tests/embind/embind.benchmark.js +++ b/tests/embind/embind.benchmark.js @@ -222,3 +222,29 @@ function _pass_gameobject_ptr_benchmark_embind_js() { Module.print("JS embind pass_gameobject_ptr " + N + " iters: " + (b-a) + " msecs."); } +function _call_through_interface0() { + var N = 1000000; + var obj = Module['Interface'].implement({ + call0: function() { + } + }); + var start = _emscripten_get_now(); + Module['callInterface0'](N, obj); + var elapsed = _emscripten_get_now() - start; + Module.print("C++ -> JS void through interface " + N + " iters: " + elapsed + " msecs."); + obj.delete(); +} + +function _call_through_interface1() { + var N = 1000000; + var obj = Module['Interface'].implement({ + call1: function(s1, s2) { + return s1 + s2; + } + }); + var start = _emscripten_get_now(); + Module['callInterface1'](N, obj); + var elapsed = _emscripten_get_now() - start; + Module.print("C++ -> JS std::wstring through interface " + N + " iters: " + elapsed + " msecs."); + obj.delete(); +} diff --git a/tests/embind/embind_benchmark.cpp b/tests/embind/embind_benchmark.cpp index cdfe998c9b839..b6a834c9d4133 100644 --- a/tests/embind/embind_benchmark.cpp +++ b/tests/embind/embind_benchmark.cpp @@ -5,8 +5,7 @@ int counter = 0; -extern "C" -{ +extern "C" { int __attribute__((noinline)) get_counter() { @@ -48,6 +47,9 @@ extern void move_gameobjects_benchmark_embind_js(); extern void pass_gameobject_ptr_benchmark(); extern void pass_gameobject_ptr_benchmark_embind_js(); + +extern void call_through_interface0(); +extern void call_through_interface1(); } class Vec3 @@ -128,6 +130,56 @@ class Foo int class_counter; }; +class Interface +{ +public: + virtual void call0() = 0; + virtual std::wstring call1(const std::wstring& str1, const std::wstring& str2) = 0; +}; + +class InterfaceWrapper : public emscripten::wrapper +{ +public: + EMSCRIPTEN_WRAPPER(InterfaceWrapper); + + void call0() override { + return call("call0"); + } + + std::wstring call1(const std::wstring& str1, const std::wstring& str2) { + return call("call1", str1, str2); + } +}; + +void callInterface0(unsigned N, Interface& o) { + for (unsigned i = 0; i < N; i += 8) { + o.call0(); + o.call0(); + o.call0(); + o.call0(); + o.call0(); + o.call0(); + o.call0(); + o.call0(); + } +} + +void callInterface1(unsigned N, Interface& o) { + static std::wstring foo(L"foo"); + static std::wstring bar(L"bar"); + static std::wstring baz(L"baz"); + static std::wstring qux(L"qux"); + for (unsigned i = 0; i < N; i += 7) { + o.call1( + o.call1( + o.call1(foo, bar), + o.call1(baz, qux)), + o.call1( + o.call1(qux, foo), + o.call1(bar, baz))); + } +} + EMSCRIPTEN_BINDINGS(benchmark) { using namespace emscripten; @@ -164,7 +216,15 @@ EMSCRIPTEN_BINDINGS(benchmark) .constructor<>() .function("incr_global_counter", &Foo::incr_global_counter) .function("incr_class_counter", &Foo::incr_class_counter) - .function("class_counter_val", &Foo::class_counter_val); + .function("class_counter_val", &Foo::class_counter_val) + ; + + class_("Interface") + .allow_subclass() + ; + + function("callInterface0", &callInterface0); + function("callInterface1", &callInterface1); } void __attribute__((noinline)) emscripten_get_now_benchmark(int N) @@ -334,6 +394,7 @@ void __attribute__((noinline)) pass_gameobject_ptr_benchmark() int main() { + /* for(int i = 1000; i <= 100000; i *= 10) emscripten_get_now_benchmark(i); @@ -370,4 +431,8 @@ int main() printf("\n"); pass_gameobject_ptr_benchmark(); pass_gameobject_ptr_benchmark_embind_js(); + */ + emscripten_get_now(); + call_through_interface0(); + call_through_interface1(); } From 2d628d429053984a3a463a9746c2b042f31e4361 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 2 May 2013 15:34:27 -0700 Subject: [PATCH 09/39] Add a test for interface methods that return void. --- tests/embind/embind.test.js | 23 +++++++++++++++++++++ tests/embind/embind_test.cpp | 40 ++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 2f407471d9324..69f933fa3d7dc 100755 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1558,6 +1558,29 @@ module({ assert.equal("optionalfoo", cm.callOptionalMethod(impl, "foo")); impl.delete(); }); + + test("void methods work", function() { + var saved = {}; + var impl = cm.AbstractClass.implement({ + differentArguments: function(i, d, f, q, s) { + saved.i = i; + saved.d = d; + saved.f = f; + saved.q = q; + saved.s = s; + } + }); + + cm.callDifferentArguments(impl, 1, 2, 3, 4, "foo"); + + assert.deepEqual(saved, { + i: 1, + d: 2, + f: 3, + q: 4, + s: "foo", + }); + }); }); BaseFixture.extend("registration order", function() { diff --git a/tests/embind/embind_test.cpp b/tests/embind/embind_test.cpp index 21fbee656cfe3..23761efc51f37 100644 --- a/tests/embind/embind_test.cpp +++ b/tests/embind/embind_test.cpp @@ -1083,6 +1083,8 @@ class AbstractClass { virtual std::string optionalMethod(std::string s) const { return "optional" + s; } + + virtual void differentArguments(int i, double d, unsigned char f, double q, std::string) = 0; }; EMSCRIPTEN_SYMBOL(optionalMethod); @@ -1094,17 +1096,26 @@ class AbstractClassWrapper : public wrapper { std::string abstractMethod() const { return call("abstractMethod"); } + std::string optionalMethod(std::string s) const { return optional_call(optionalMethod_symbol, [&] { return AbstractClass::optionalMethod(s); }, s); } + + void differentArguments(int i, double d, unsigned char f, double q, std::string s) { + return call("differentArguments", i, d, f, q, s); + } }; class ConcreteClass : public AbstractClass { std::string abstractMethod() const { return "from concrete"; } + + + void differentArguments(int i, double d, unsigned char f, double q, std::string s) { + } }; std::shared_ptr getAbstractClass() { @@ -1119,6 +1130,24 @@ std::string callOptionalMethod(AbstractClass& ac, std::string s) { return ac.optionalMethod(s); } +void callDifferentArguments(AbstractClass& ac, int i, double d, unsigned char f, double q, std::string s) { + return ac.differentArguments(i, d, f, q, s); +} + +EMSCRIPTEN_BINDINGS(interface_tests) { + class_("AbstractClass") + .smart_ptr>() + .allow_subclass() + .function("abstractMethod", &AbstractClass::abstractMethod) + .function("optionalMethod", &AbstractClass::optionalMethod) + ; + + function("getAbstractClass", &getAbstractClass); + function("callAbstractMethod", &callAbstractMethod); + function("callOptionalMethod", &callOptionalMethod); + function("callDifferentArguments", &callDifferentArguments); +} + class HasExternalConstructor { public: HasExternalConstructor(const std::string& str) @@ -1750,17 +1779,6 @@ EMSCRIPTEN_BINDINGS(tests) { function("embind_test_new_Object", &embind_test_new_Object); function("embind_test_new_factory", &embind_test_new_factory); - class_("AbstractClass") - .smart_ptr>() - .allow_subclass() - .function("abstractMethod", &AbstractClass::abstractMethod) - .function("optionalMethod", &AbstractClass::optionalMethod) - ; - - function("getAbstractClass", &getAbstractClass); - function("callAbstractMethod", &callAbstractMethod); - function("callOptionalMethod", &callOptionalMethod); - class_("HasExternalConstructor") .constructor(&createHasExternalConstructor) .function("getString", &HasExternalConstructor::getString) From 8237fb35bcfb721eefb9c1608856b36a6adb852e Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Thu, 2 May 2013 16:05:57 -0700 Subject: [PATCH 10/39] Oops, fix a test leak. --- tests/embind/build_benchmark | 2 +- tests/embind/embind.test.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/embind/build_benchmark b/tests/embind/build_benchmark index f878a2d409d9e..6faad18bc202a 100755 --- a/tests/embind/build_benchmark +++ b/tests/embind/build_benchmark @@ -1,2 +1,2 @@ #!/bin/bash -EMCC_LLVM_TARGET=le32-unknown-nacl ~/projects/emscripten/emcc --minify 0 --bind --pre-js embind.benchmark.js -O2 --shell-file shell.html -o embind_benchmark.html embind_benchmark.cpp +EMCC_LLVM_TARGET=le32-unknown-nacl ~/projects/emscripten/emcc --minify 0 --bind --post-js embind.benchmark.js -O2 --shell-file shell.html -o embind_benchmark.html embind_benchmark.cpp diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js index 69f933fa3d7dc..52b2cad8ce654 100755 --- a/tests/embind/embind.test.js +++ b/tests/embind/embind.test.js @@ -1580,6 +1580,8 @@ module({ q: 4, s: "foo", }); + + impl.delete(); }); }); From 34bce791b6b1c34e85c5deda7fb71869dcdd6435 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2013 19:07:20 -0700 Subject: [PATCH 11/39] only emit aborting function stubs on undefined symbols in asm mode --- src/jsifier.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/jsifier.js b/src/jsifier.js index 24fded7213c5a..46d8ae74793ca 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -486,12 +486,18 @@ function JSify(data, functionsOnly, givenFunctions) { item.JS = ''; } else { // If this is not linkable, anything not in the library is definitely missing + var cancel = false; if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) { if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident); if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) printErr('warning: unresolved symbol: ' + shortident); - LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); + if (ASM_JS) { + // emit a stub that will fail during runtime. this allows asm validation to succeed. + LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); + } else { + cancel = true; // emit nothing, not even var X = undefined; + } } - item.JS = addFromLibrary(shortident); + item.JS = cancel ? ';' : addFromLibrary(shortident); } return ret; } From ce122916a38c1fdc8b82e3eb4804c979fe06a242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Sat, 27 Apr 2013 13:06:42 +0200 Subject: [PATCH 12/39] * Added some colors to messages displayed from python files. --- emcc | 137 +++++++++++++++++++------------------- tools/shared.py | 174 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 202 insertions(+), 109 deletions(-) diff --git a/emcc b/emcc index 3df6523692882..7e020a612a0dc 100755 --- a/emcc +++ b/emcc @@ -75,12 +75,14 @@ emcc can be influenced by a few environment variables: EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang. ''' -import os, sys, shutil, tempfile, subprocess, shlex, time, re +import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging from subprocess import PIPE, STDOUT from tools import shared from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename from tools.response_file import read_response_file +logging = logging.getLogger('emcc') + # Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt # levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get # llvm opt level 3, and speed-wise emcc level 2 is already the slowest/most optimizing @@ -107,10 +109,10 @@ AUTODEBUG = os.environ.get('EMCC_AUTODEBUG') # If set to 1, we will run the auto # dlmalloc makes it hard to compare native and js builds EMCC_CFLAGS = os.environ.get('EMCC_CFLAGS') # Additional compiler flags that we treat as if they were passed to us on the commandline -if DEBUG: print >> sys.stderr, '\nemcc invocation: ', ' '.join(sys.argv), (' + ' + EMCC_CFLAGS if EMCC_CFLAGS else '') +logging.debug('invocation: ' + ' '.join(sys.argv) + (' + ' + EMCC_CFLAGS if EMCC_CFLAGS else '')) if EMCC_CFLAGS: sys.argv.append(EMCC_CFLAGS) -if DEBUG and LEAVE_INPUTS_RAW: print >> sys.stderr, 'emcc: leaving inputs raw' +if DEBUG and LEAVE_INPUTS_RAW: logging.error('leaving inputs raw') stdout = PIPE if not DEBUG else None # suppress output of child processes stderr = PIPE if not DEBUG else None # unless we are in DEBUG mode @@ -120,7 +122,7 @@ shared.check_sanity(force=DEBUG) # Handle some global flags if len(sys.argv) == 1: - print 'emcc: no input files' + logging.error('no input files') exit(1) # read response files very early on @@ -506,7 +508,7 @@ def is_minus_s_for_emcc(newargs,i): if i+1 < len(newargs) and '=' in newargs[i+1]: # -s OPT=VALUE is for us, -s by itself is a linker option return True else: - print >> sys.stderr, 'emcc: warning: treating -s as linker option and not as -s OPT=VALUE for js compilation' + logging.warning('treating -s as linker option and not as -s OPT=VALUE for js compilation') return False # If this is a configure-type thing, do not compile to JavaScript, instead use clang @@ -563,7 +565,7 @@ if CONFIGURE_CONFIG or CMAKE_CONFIG: if not use_js: cmd += shared.EMSDK_OPTS + ['-DEMSCRIPTEN'] if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists - if DEBUG: print >> sys.stderr, 'emcc, just configuring: ', ' '.join(cmd) + logging.debug('just configuring: ' + ' '.join(cmd)) if debug_configure: open(tempout, 'a').write('emcc, just configuring: ' + ' '.join(cmd) + '\n\n') if not use_js: @@ -634,7 +636,7 @@ def uniquename(name): if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']: # noop ar - if DEBUG: print >> sys.stderr, 'emcc, just ar' + logging.debug('just ar') sys.exit(0) use_cxx = True @@ -651,7 +653,7 @@ for i in range(1, len(sys.argv)): if '-M' in sys.argv or '-MM' in sys.argv: # Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it) cmd = [CC] + shared.COMPILER_OPTS + sys.argv[1:] - if DEBUG: print >> sys.stderr, 'emcc, just dependencies: ', ' '.join(cmd) + logging.debug('just dependencies: ' + ' '.join(cmd)) exit(subprocess.call(cmd)) # Check if a target is specified @@ -677,10 +679,10 @@ else: if header: # header or such if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv) - if DEBUG: print >> sys.stderr, 'Just copy:', sys.argv[-1], target + logging.debug('Just copy:' + sys.argv[-1] + target) shutil.copy(sys.argv[-1], target) else: - if DEBUG: print >> sys.stderr, 'No-op.' + logging.debug('No-op.') exit(0) if TEMP_DIR: @@ -847,14 +849,14 @@ try: newargs[i] = '' newargs[i+1] = '' elif newargs[i] == '--remove-duplicates': - print >> sys.stderr, 'emcc: warning: --remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase' + logging.warning ('--remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase') newargs[i] = '' elif newargs[i] == '--jcache': jcache = True newargs[i] = '' elif newargs[i] == '--clear-cache': newargs[i] = '' - print >> sys.stderr, 'emcc: clearing cache' + logging.info('clearing cache') shared.Cache.erase() sys.exit(0) elif newargs[i] == '--save-bc': @@ -869,7 +871,7 @@ try: newargs[i+1] = '' elif newargs[i].startswith(('-I/', '-L/')): if not absolute_warning_shown: - print >> sys.stderr, 'emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not + logging.warning ('-I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)') # Of course an absolute path to a non-system-specific library or header is fine, and you can ignore this warning. The danger are system headers that are e.g. x86 specific and nonportable. The emscripten bundled headers are modified to be portable, local system ones are generally not absolute_warning_shown = True newargs = [ arg for arg in newargs if arg is not '' ] @@ -886,7 +888,7 @@ try: if DEBUG: start_time = time.time() # done after parsing arguments, which might affect debug state if closure: - assert os.path.exists(shared.CLOSURE_COMPILER), 'emcc: fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER + assert os.path.exists(shared.CLOSURE_COMPILER), logging.error('fatal: Closure compiler (%s) does not exist' % shared.CLOSURE_COMPILER) for i in range(len(newargs)): if newargs[i] == '-s': @@ -939,9 +941,9 @@ try: libs.append(l) newargs[i] = '' else: - print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg + logging.warning(arg + ' is not valid LLVM bitcode') else: - print >> sys.stderr, 'emcc: %s: error: No such file or directory' % arg + logging.error(arg + ': No such file or directory') exit(1) elif arg.startswith('-L'): lib_dirs.append(arg[2:]) @@ -963,12 +965,12 @@ try: # do not link in libs when just generating object code (not an 'executable', i.e. JS, or a library) if ('.' + final_suffix) in BITCODE_SUFFIXES and len(libs) > 0: - print >> sys.stderr, 'emcc: warning: not linking against libraries since only compiling to bitcode' + logging.warning('not linking against libraries since only compiling to bitcode') libs = [] # Find library files for lib in libs: - if DEBUG: print >> sys.stderr, 'emcc: looking for library "%s"' % lib + logging.debug('looking for library "%s"' % lib) found = False for prefix in LIB_PREFIXES: for suff in STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES: @@ -976,7 +978,7 @@ try: for lib_dir in lib_dirs: path = os.path.join(lib_dir, name) if os.path.exists(path): - if DEBUG: print >> sys.stderr, 'emcc: found library "%s" at %s' % (lib, path) + logging.debug('found library "%s" at %s' % (lib, path)) input_files.append(path) found = True break @@ -987,8 +989,7 @@ try: input_files = filter(lambda input_file: not input_file.endswith(DYNAMICLIB_SUFFIXES), input_files) if len(input_files) == 0: - print >> sys.stderr, 'emcc: no input files' - print >> sys.stderr, 'note that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) + logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + STATICLIB_SUFFIXES + ASSEMBLY_SUFFIXES)) exit(0) newargs += CC_ADDITIONAL_ARGS @@ -1015,15 +1016,15 @@ try: if bind: shared.Settings.ASM_JS = 0 - print >> sys.stderr, 'emcc: warning: disabling asm.js because it is not compatible with embind yet' + logging.warning('disabling asm.js because it is not compatible with embind yet') if closure: - print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation' + logging.warning('disabling closure because it is not compatible with asm.js code generation') closure = False if shared.Settings.CORRECT_SIGNS != 1: - print >> sys.stderr, 'emcc: warning: setting CORRECT_SIGNS to 1 for asm.js code generation' + logging.warning('setting CORRECT_SIGNS to 1 for asm.js code generation') shared.Settings.CORRECT_SIGNS = 1 if shared.Settings.CORRECT_OVERFLOWS != 1: - print >> sys.stderr, 'emcc: warning: setting CORRECT_OVERFLOWS to 1 for asm.js code generation' + logging.warning('setting CORRECT_OVERFLOWS to 1 for asm.js code generation') shared.Settings.CORRECT_OVERFLOWS = 1 assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode' @@ -1031,7 +1032,7 @@ try: keep_llvm_debug = True # must keep debug info to do line-by-line operations if (keep_llvm_debug or keep_js_debug) and closure: - print >> sys.stderr, 'emcc: warning: disabling closure because debug info was requested' + logging.warning('disabling closure because debug info was requested') closure = False if jcache and not keep_js_debug: print >> sys.stderr, 'emcc: warning: it is recommended to run jcache with -g when compiling bitcode to JS' @@ -1053,31 +1054,31 @@ try: ## Compile source code to bitcode - if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode' + logging.debug('compiling to bitcode') temp_files = [] # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): - if DEBUG: print >> sys.stderr, 'emcc: compiling source file: ', input_file + logging.debug('compiling source file: ' + input_file) input_file = shared.Building.preprocess(input_file, in_temp(uniquename(input_file))) output_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') temp_files.append(output_file) args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] - if DEBUG: print >> sys.stderr, "emcc running:", call, ' '.join(args) + logging.debug("running:" + call + ' '.join(args)) execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that) if not os.path.exists(output_file): - print >> sys.stderr, 'emcc: compiler frontend failed to generate LLVM bitcode, halting' + logging.error('compiler frontend failed to generate LLVM bitcode, halting') sys.exit(1) else: # bitcode if input_file.endswith(BITCODE_SUFFIXES): - if DEBUG: print >> sys.stderr, 'emcc: copying bitcode file: ', input_file + logging.debug('copying bitcode file: ' + input_file) temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') shutil.copyfile(input_file, temp_file) temp_files.append(temp_file) elif input_file.endswith(DYNAMICLIB_SUFFIXES) or shared.Building.is_ar(input_file): - if DEBUG: print >> sys.stderr, 'emcc: copying library file: ', input_file + logging.debug('copying library file: ' + input_file) temp_file = in_temp(uniquename(input_file)) shutil.copyfile(input_file, temp_file) temp_files.append(temp_file) @@ -1085,7 +1086,7 @@ try: if not LEAVE_INPUTS_RAW: # Note that by assembling the .ll file, then disassembling it later, we will # remove annotations which is a good thing for compilation time - if DEBUG: print >> sys.stderr, 'emcc: assembling assembly file: ', input_file + logging.debug('assembling assembly file: ' + input_file) temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') shared.Building.llvm_as(input_file, temp_file) temp_files.append(temp_file) @@ -1096,14 +1097,14 @@ try: if final_suffix not in JS_CONTAINING_SUFFIXES: if llvm_opts > 0: if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'): - print >> sys.stderr, 'emcc: warning: -Ox flags ignored, since not generating JavaScript' + logging.warning('-Ox flags ignored, since not generating JavaScript') else: for input_file in input_files: if input_file.endswith(SOURCE_SUFFIXES): - if DEBUG: print >> sys.stderr, 'emcc: optimizing %s with -O%d since EMCC_OPTIMIZE_NORMALLY defined' % (input_file, llvm_opts) + logging.debug('optimizing %s with -O%d since EMCC_OPTIMIZE_NORMALLY defined' % (input_file, llvm_opts)) shared.Building.llvm_opt(in_temp(unsuffixed(uniquename(input_file)) + '.o'), llvm_opts) else: - if DEBUG: print >> sys.stderr, 'emcc: not optimizing %s despite EMCC_OPTIMIZE_NORMALLY since not source code' % (input_file) + logging.debug('not optimizing %s despite EMCC_OPTIMIZE_NORMALLY since not source code' % (input_file)) if not specified_target: for input_file in input_files: shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) @@ -1114,13 +1115,13 @@ try: assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files) # We have a specified target (-o ), which is not JavaScript or HTML, and # we have multiple files: Link them - if DEBUG: print >> sys.stderr, 'emcc: link: ' + str(temp_files), specified_target + logging.debug('link: ' + str(temp_files) + specified_target) shared.Building.link(temp_files, specified_target) exit(0) ## Continue on to create JavaScript - if DEBUG: print >> sys.stderr, 'emcc: will generate JavaScript' + logging.debug('will generate JavaScript') extra_files_to_link = [] @@ -1169,7 +1170,7 @@ try: # libc def create_libc(): - if DEBUG: print >> sys.stderr, 'emcc: building libc for cache' + logging.debug(' building libc for cache') libc_files = [ 'dlmalloc.c', os.path.join('libcxx', 'new.cpp'), @@ -1199,7 +1200,7 @@ try: # libcextra def create_libcextra(): - if DEBUG: print >> sys.stderr, 'emcc: building libcextra for cache' + logging.debug('building libcextra for cache') musl_files = [ ['ctype', [ 'iswalnum.c', @@ -1278,7 +1279,7 @@ try: # libcxx def create_libcxx(): - if DEBUG: print >> sys.stderr, 'emcc: building libcxx for cache' + logging.debug('building libcxx for cache') libcxx_files = [ 'algorithm.cpp', 'condition_variable.cpp', @@ -1309,11 +1310,11 @@ try: assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1' # libcxx might need corrections, so turn them all on. TODO: check which are actually needed shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1 - #print >> sys.stderr, 'emcc: info: using libcxx turns on CORRECT_* options' + #logging.info('using libcxx turns on CORRECT_* options') # libcxxabi - just for dynamic_cast for now def create_libcxxabi(): - if DEBUG: print >> sys.stderr, 'emcc: building libcxxabi for cache' + logging.debug('building libcxxabi for cache') libcxxabi_files = [ 'typeinfo.cpp', 'private_typeinfo.cpp' @@ -1322,7 +1323,7 @@ try: def fix_libcxxabi(need): assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1' - #print >> sys.stderr, 'emcc: info: using libcxxabi, this may need CORRECT_* options' + #logging.info('using libcxxabi, this may need CORRECT_* options') #shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1 # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky @@ -1346,10 +1347,10 @@ try: for haz in has: # remove symbols that are supplied by another of the inputs if haz in need: need.remove(haz) - if DEBUG: print >> sys.stderr, 'emcc: considering including %s: we need %s and have %s' % (name, str(need), str(has)) + logging.debug('considering including %s: we need %s and have %s' % (name, str(need), str(has))) if force or len(need) > 0: # We need to build and link the library in - if DEBUG: print >> sys.stderr, 'emcc: including %s' % name + logging.debug('including %s' % name) libfile = shared.Cache.get(name, create) extra_files_to_link.append(libfile) force = True @@ -1360,11 +1361,11 @@ try: if len(input_files) + len(extra_files_to_link) > 1 or \ (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])): linker_inputs = temp_files + extra_files_to_link - if DEBUG: print >> sys.stderr, 'emcc: linking: ', linker_inputs + logging.debug('linking: ', linker_inputs) t0 = time.time() shared.Building.link(linker_inputs, in_temp(target_basename + '.bc')) t1 = time.time() - if DEBUG: print >> sys.stderr, 'emcc: linking took %.2f seconds' % (t1 - t0) + logging.debug(' linking took %.2f seconds' % (t1 - t0)) final = in_temp(target_basename + '.bc') else: if not LEAVE_INPUTS_RAW: @@ -1375,7 +1376,7 @@ try: shutil.copyfile(input_files[0], final) if DEBUG: - print >> sys.stderr, 'emcc: saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR + logging.debug('saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR) intermediate_counter = 0 intermediate_time = None @@ -1385,7 +1386,7 @@ try: intermediate_counter += 1 now = time.time() if intermediate_time: - print >> sys.stderr, 'emcc: step took %.2f seconds' % (now - intermediate_time) + logging.debug(' step took %.2f seconds' % (now - intermediate_time)) intermediate_time = now if not LEAVE_INPUTS_RAW: save_intermediate('basebc', 'bc') @@ -1399,7 +1400,7 @@ try: if DEBUG: save_intermediate('opt', 'bc') # Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript) else: - if DEBUG: print >> sys.stderr, 'emcc: not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before' + logging.debug('not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before') if shared.Building.can_build_standalone(): # If we can LTO, do it before dce, since it opens up dce opportunities if llvm_lto and shared.Building.can_use_unsafe_opts(): @@ -1423,13 +1424,13 @@ try: if DEBUG: save_intermediate('ll', 'll') if AUTODEBUG: - if DEBUG: print >> sys.stderr, 'emcc: autodebug' + logging.debug('autodebug') execute([shared.PYTHON, shared.AUTODEBUGGER, final, final + '.ad.ll']) final += '.ad.ll' if DEBUG: save_intermediate('autodebug', 'll') # Emscripten - if DEBUG: print >> sys.stderr, 'emcc: LLVM => JS' + logging.debug('LLVM => JS') extra_args = [] if not js_libraries else ['--libraries', ','.join(map(os.path.abspath, js_libraries))] if jcache: extra_args.append('--jcache') final = shared.Building.emscripten(final, append_ext=False, extra_args=extra_args) @@ -1437,7 +1438,7 @@ try: # Embed and preload files if len(preload_files) + len(embed_files) > 0: - if DEBUG: print >> sys.stderr, 'emcc: setting up files' + logging.debug('setting up files') file_args = [] if len(preload_files) > 0: file_args.append('--preload') @@ -1457,7 +1458,7 @@ try: # Apply pre and postjs files if pre_js or post_js: - if DEBUG: print >> sys.stderr, 'emcc: applying pre/postjses' + logging.debug('applying pre/postjses') src = open(final).read() final += '.pp.js' open(final, 'w').write(pre_js + src + post_js) @@ -1465,7 +1466,7 @@ try: # Add bindings glue if used if bind: - if DEBUG: print >> sys.stderr, 'emcc: adding embind glue' + logging.debug('adding embind glue') src = open(final).read().replace('// {{PRE_RUN_ADDITIONS}}', '// {{PRE_RUN_ADDITIONS}}\n' + open(shared.path_from_root('src', 'embind', 'embind.js')).read() + open(shared.path_from_root('src', 'embind', 'emval.js')).read() @@ -1479,7 +1480,7 @@ try: shutil.copyfile(final, final + '.tr.js') final += '.tr.js' posix = True if not shared.WINDOWS else False - if DEBUG: print >> sys.stderr, 'emcc: applying transform: %s' % js_transform + logging.debug('applying transform: %s' % js_transform) execute(shlex.split(js_transform, posix=posix) + [os.path.abspath(final)]) if DEBUG: save_intermediate('transformed') @@ -1491,7 +1492,7 @@ try: if DEBUG != '2': if shared.Settings.ASM_JS: js_optimizer_queue = ['asm'] + js_optimizer_queue - if DEBUG: print >> sys.stderr, 'emcc: applying js optimization passes:', js_optimizer_queue + logging.debug('applying js optimization passes:', js_optimizer_queue) final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache) if DEBUG: save_intermediate('js_opts') else: @@ -1499,13 +1500,13 @@ try: passes = [name] if shared.Settings.ASM_JS: passes = ['asm'] + passes - print >> sys.stderr, 'emcc: applying js optimization pass:', passes + logging.info('applying js optimization pass:', passes) final = shared.Building.js_optimizer(final, passes, jcache) save_intermediate(name) js_optimizer_queue = [] if opt_level >= 1: - if DEBUG: print >> sys.stderr, 'emcc: running pre-closure post-opts' + logging.debug('running pre-closure post-opts') if DEBUG == '2': # Clean up the syntax a bit @@ -1526,12 +1527,12 @@ try: if closure: flush_js_optimizer_queue() - if DEBUG: print >> sys.stderr, 'emcc: running closure' + logging.debug('running closure') final = shared.Building.closure_compiler(final) if DEBUG: save_intermediate('closure') if opt_level >= 1: - if DEBUG: print >> sys.stderr, 'emcc: running post-closure post-opts' + logging.debug('running post-closure post-opts') js_optimizer_queue += ['simplifyExpressionsPost'] if not closure and shared.Settings.RELOOP and not keep_js_debug: @@ -1552,7 +1553,7 @@ try: if memory_init_file: if shared.Settings.USE_TYPED_ARRAYS != 2: - if type(memory_init_file) == int: print >> sys.stderr, 'emcc: warning: memory init file requires typed arrays mode 2' + if type(memory_init_file) == int: logging.warning('memory init file requires typed arrays mode 2') else: memfile = target + '.mem' shared.try_delete(memfile) @@ -1574,13 +1575,13 @@ try: if DEBUG: if os.path.exists(memfile): save_intermediate('meminit') - print >> sys.stderr, 'emcc: wrote memory initialization to %s' % memfile + logging.debug('wrote memory initialization to %s' % memfile) else: - print >> sys.stderr, 'emcc: did not see memory initialization' + logging.debug('did not see memory initialization') # If we were asked to also generate HTML, do that if final_suffix == 'html': - if DEBUG: print >> sys.stderr, 'emcc: generating HTML' + logging.debug('generating HTML') shell = open(shell_path).read() html = open(target, 'w') if not Compression.on: @@ -1657,7 +1658,7 @@ try: # copy final JS to output shutil.move(final, target) - if DEBUG: print >> sys.stderr, 'emcc: total time: %.2f seconds' % (time.time() - start_time) + if DEBUG: logging.debug('total time: %.2f seconds' % (time.time() - start_time)) finally: if not TEMP_DIR: @@ -1666,5 +1667,5 @@ finally: except: pass else: - print >> sys.stderr, 'emcc saved files are in:', temp_dir + logging.info('emcc saved files are in:' + temp_dir) diff --git a/tools/shared.py b/tools/shared.py index e9284bf70a8c0..97d30f0caff16 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -3,6 +3,7 @@ from tempfile import mkstemp import jsrun, cache, tempfiles from response_file import create_response_file +import logging, platform def listify(x): if type(x) is not list: return [x] @@ -90,6 +91,100 @@ def __del__(self): def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) +def add_coloring_to_emit_windows(fn): + def _out_handle(self): + import ctypes + return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) + out_handle = property(_out_handle) + + def _set_color(self, code): + import ctypes + # Constants from the Windows API + self.STD_OUTPUT_HANDLE = -11 + hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE) + ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code) + + setattr(logging.StreamHandler, '_set_color', _set_color) + + def new(*args): + FOREGROUND_BLUE = 0x0001 # text color contains blue. + FOREGROUND_GREEN = 0x0002 # text color contains green. + FOREGROUND_RED = 0x0004 # text color contains red. + FOREGROUND_INTENSITY = 0x0008 # text color is intensified. + FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED + # winbase.h + STD_INPUT_HANDLE = -10 + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + + # wincon.h + FOREGROUND_BLACK = 0x0000 + FOREGROUND_BLUE = 0x0001 + FOREGROUND_GREEN = 0x0002 + FOREGROUND_CYAN = 0x0003 + FOREGROUND_RED = 0x0004 + FOREGROUND_MAGENTA = 0x0005 + FOREGROUND_YELLOW = 0x0006 + FOREGROUND_GREY = 0x0007 + FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified. + + BACKGROUND_BLACK = 0x0000 + BACKGROUND_BLUE = 0x0010 + BACKGROUND_GREEN = 0x0020 + BACKGROUND_CYAN = 0x0030 + BACKGROUND_RED = 0x0040 + BACKGROUND_MAGENTA = 0x0050 + BACKGROUND_YELLOW = 0x0060 + BACKGROUND_GREY = 0x0070 + BACKGROUND_INTENSITY = 0x0080 # background color is intensified. + levelno = args[1].levelno + if(levelno>=50): + color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY + elif(levelno>=40): + color = FOREGROUND_RED | FOREGROUND_INTENSITY + elif(levelno>=30): + color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY + elif(levelno>=20): + color = FOREGROUND_GREEN + elif(levelno>=10): + color = FOREGROUND_MAGENTA + else: + color = FOREGROUND_WHITE + args[0]._set_color(color) + ret = fn(*args) + args[0]._set_color( FOREGROUND_WHITE ) + #print "after" + return ret + return new + +def add_coloring_to_emit_ansi(fn): + # add methods we need to the class + def new(*args): + levelno = args[1].levelno + if(levelno>=50): + color = '\x1b[31m' # red + elif(levelno>=40): + color = '\x1b[31m' # red + elif(levelno>=30): + color = '\x1b[33m' # yellow + elif(levelno>=20): + color = '\x1b[32m' # green + elif(levelno>=10): + color = '\x1b[35m' # pink + else: + color = '\x1b[0m' # normal + args[1].msg = color + args[1].msg + '\x1b[0m' # normal + #print "after" + return fn(*args) + return new + +WINDOWS = sys.platform.startswith('win') + +if WINDOWS: + logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit) +else: + logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit) + # Emscripten configuration is done through the EM_CONFIG environment variable. # If the string value contained in this environment variable contains newline # separated definitions, then these definitions will be used to configure @@ -157,7 +252,7 @@ def path_from_root(*pathelems): config_text = open(CONFIG_FILE, 'r').read() if CONFIG_FILE else EM_CONFIG exec(config_text) except Exception, e: - print >> sys.stderr, 'Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text) + logging.error('Error in evaluating %s (at %s): %s, text: %s' % (EM_CONFIG, CONFIG_FILE, str(e), config_text)) sys.exit(1) # Expectations @@ -169,14 +264,14 @@ def check_clang_version(): actual = Popen([CLANG, '-v'], stderr=PIPE).communicate()[1].split('\n')[0] if expected in actual: return True - print >> sys.stderr, 'warning: LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected) + logging.warning('LLVM version appears incorrect (seeing "%s", expected "%s")' % (actual, expected)) return False def check_llvm_version(): try: check_clang_version(); except Exception, e: - print >> sys.stderr, 'warning: Could not verify LLVM version: %s' % str(e) + logging.warning('Could not verify LLVM version: %s' % str(e)) EXPECTED_NODE_VERSION = (0,6,8) @@ -187,10 +282,10 @@ def check_node_version(): version = tuple(map(int, actual.replace('v', '').split('.'))) if version >= EXPECTED_NODE_VERSION: return True - print >> sys.stderr, 'warning: node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION)))) + logging.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION))))) return False except Exception, e: - print >> sys.stderr, 'warning: cannot check node version:', e + logging.warning('cannot check node version:' + e) return False # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) @@ -227,7 +322,7 @@ def check_sanity(force=False): except Exception, e: reason = 'unknown: ' + str(e) if reason: - print >> sys.stderr, '(Emscripten: %s, clearing cache)' % reason + logging.info('(Emscripten: %s, clearing cache)' % reason) Cache.erase() # some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on @@ -235,32 +330,32 @@ def check_sanity(force=False): check_node_version() if os.environ.get('EM_IGNORE_SANITY'): - print >> sys.stderr, 'EM_IGNORE_SANITY set, ignoring sanity checks' + logging.info('EM_IGNORE_SANITY set, ignoring sanity checks') return - print >> sys.stderr, '(Emscripten: Running sanity checks)' + logging.info('(Emscripten: Running sanity checks)') if not check_engine(COMPILER_ENGINE): - print >> sys.stderr, 'FATAL: The JavaScript shell used for compiling (%s) does not seem to work, check the paths in %s' % (COMPILER_ENGINE, EM_CONFIG) + logging.critical('The JavaScript shell used for compiling (%s) does not seem to work, check the paths in %s' % (COMPILER_ENGINE, EM_CONFIG)) sys.exit(1) if NODE_JS != COMPILER_ENGINE: if not check_engine(NODE_JS): - print >> sys.stderr, 'FATAL: Node.js (%s) does not seem to work, check the paths in %s' % (NODE_JS, EM_CONFIG) + logging.critical('Node.js (%s) does not seem to work, check the paths in %s' % (NODE_JS, EM_CONFIG)) sys.exit(1) for cmd in [CLANG, LLVM_LINK, LLVM_AR, LLVM_OPT, LLVM_AS, LLVM_DIS, LLVM_NM]: if not os.path.exists(cmd) and not os.path.exists(cmd + '.exe'): # .exe extension required for Windows - print >> sys.stderr, 'FATAL: Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG) + logging.critical('Cannot find %s, check the paths in %s' % (cmd, EM_CONFIG)) sys.exit(1) try: subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE) except: - print >> sys.stderr, 'WARNING: java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten' + logging.warning('java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten') if not os.path.exists(CLOSURE_COMPILER): - print >> sys.stderr, 'WARNING: Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG) + logging.warning('Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG)) # Sanity check passed! @@ -335,7 +430,7 @@ def __init__(self, environ): try: self.TEMP_DIR = TEMP_DIR except NameError: - print >> sys.stderr, 'TEMP_DIR not defined in ~/.emscripten, using /tmp' + logging.info('TEMP_DIR not defined in ~/.emscripten, using /tmp') self.TEMP_DIR = '/tmp' self.CANONICAL_TEMP_DIR = os.path.join(self.TEMP_DIR, 'emscripten_temp') @@ -346,23 +441,22 @@ def __init__(self, environ): if not os.path.exists(self.EMSCRIPTEN_TEMP_DIR): os.makedirs(self.EMSCRIPTEN_TEMP_DIR) except Exception, e: - print >> sys.stderr, e, 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten' + logging.debug(e + 'Could not create canonical temp dir. Check definition of TEMP_DIR in ~/.emscripten') def get_temp_files(self): return tempfiles.TempFiles( tmp=self.TEMP_DIR if not self.DEBUG else self.EMSCRIPTEN_TEMP_DIR, save_debug_files=os.environ.get('EMCC_DEBUG_SAVE')) - def debug_log(self, msg): - if self.DEBUG: - print >> sys.stderr, msg - configuration = Configuration(environ=os.environ) DEBUG = configuration.DEBUG EMSCRIPTEN_TEMP_DIR = configuration.EMSCRIPTEN_TEMP_DIR DEBUG_CACHE = configuration.DEBUG_CACHE CANONICAL_TEMP_DIR = configuration.CANONICAL_TEMP_DIR +level = logging.DEBUG if os.environ.get('EMCC_DEBUG') else logging.INFO +logging.basicConfig(level=level, format='%(levelname)-8s %(name)s: %(message)s') + if not EMSCRIPTEN_TEMP_DIR: EMSCRIPTEN_TEMP_DIR = tempfile.mkdtemp(prefix='emscripten_temp_', dir=configuration.TEMP_DIR) def clean_temp(): @@ -388,13 +482,13 @@ def clean_temp(): try: PYTHON except: - if DEBUG: print >> sys.stderr, 'PYTHON not defined in ~/.emscripten, using "python"' + logging.debug('PYTHON not defined in ~/.emscripten, using "python"') PYTHON = 'python' try: JAVA except: - if DEBUG: print >> sys.stderr, 'JAVA not defined in ~/.emscripten, using "java"' + logging.debug('JAVA not defined in ~/.emscripten, using "java"') JAVA = 'java' # Additional compiler options @@ -450,8 +544,6 @@ def get_llvm_target(): except NameError: pass -WINDOWS = sys.platform.startswith('win') - # If we have 'env', we should use that to find python, because |python| may fail while |env python| may work # (For example, if system python is 3.x while we need 2.x, and env gives 2.x if told to do so.) ENV_PREFIX = [] @@ -585,7 +677,7 @@ def apply_opt_level(self, opt_level, noisy=False): # Aside from these, -O3 also runs closure compiler and llvm lto Settings.DOUBLE_MODE = 0 Settings.PRECISE_I64_MATH = 0 - if noisy: print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)' + if noisy: logging.warning('Applying some potentially unsafe optimizations! (Use -O2 if this fails.)') global Settings Settings = Settings2 @@ -671,7 +763,7 @@ def configure(args, stdout=None, stderr=None, env=None): process = Popen(args, stdout=stdout, stderr=stderr, env=env) process.communicate() except Exception, e: - print >> sys.stderr, 'Error: Exception thrown when invoking Popen in configure with args: "%s"!' % ' '.join(args) + logging.error('Exception thrown when invoking Popen in configure with args: "%s"!' % ' '.join(args)) raise del env['EMMAKEN_JUST_CONFIGURE'] if process.returncode is not 0: @@ -682,14 +774,14 @@ def make(args, stdout=None, stderr=None, env=None): if env is None: env = Building.get_building_env() if not args: - print >> sys.stderr, 'Error: Executable to run not specified.' + logging.error('Executable to run not specified.') sys.exit(1) #args += ['VERBOSE=1'] try: process = Popen(args, stdout=stdout, stderr=stderr, env=env) process.communicate() except Exception, e: - print >> sys.stderr, 'Error: Exception thrown when invoking Popen in make with args: "%s"!' % ' '.join(args) + logging.error('Exception thrown when invoking Popen in make with args: "%s"!' % ' '.join(args)) raise if process.returncode is not 0: raise subprocess.CalledProcessError(cmd=args, returncode=process.returncode) @@ -796,7 +888,7 @@ def link(files, target): contents = filter(lambda x: len(x) > 0, Popen([LLVM_AR, 't', f], stdout=PIPE).communicate()[0].split('\n')) #print >> sys.stderr, ' considering archive', f, ':', contents if len(contents) == 0: - print >> sys.stderr, 'Warning: Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f + logging.debug('Archive %s appears to be empty (recommendation: link an .so instead of .a)' % f) else: for content in contents: # ar will silently fail if the directory for the file does not exist, so make all the necessary directories dirname = os.path.dirname(content) @@ -833,7 +925,7 @@ def link(files, target): # Finish link actual_files = unique_ordered(actual_files) # tolerate people trying to link a.so a.so etc. - if DEBUG: print >>sys.stderr, 'emcc: llvm-linking:', actual_files + logging.debug('emcc: llvm-linking:', actual_files) # check for too-long command line link_cmd = [LLVM_LINK] + actual_files + ['-o', target] @@ -841,7 +933,7 @@ def link(files, target): # for max command line size before we use a respose file response_file = None if WINDOWS and len(' '.join(link_cmd)) > 8192: - if DEBUG: print >>sys.stderr, 'using response file for llvm-link' + logging.debug('using response file for llvm-link') [response_fd, response_file] = mkstemp(suffix='.response', dir=TEMP_DIR) link_cmd = [LLVM_LINK, "@" + response_file] @@ -858,7 +950,7 @@ def link(files, target): link_cmd.append(target) if len(' '.join(link_cmd)) > 8192: - print >>sys.stderr, 'emcc: warning: link command line is very long, even with response file -- use paths with no spaces' + logging.warning('emcc: link command line is very long, even with response file -- use paths with no spaces') output = Popen(link_cmd, stdout=PIPE).communicate()[0] @@ -887,7 +979,7 @@ def llvm_opt(filename, opts): if type(opts) is int: opts = Building.pick_llvm_opts(opts) #opts += ['-debug-pass=Arguments'] - if DEBUG: print >> sys.stderr, 'emcc: LLVM opts:', opts + logging.debug('emcc: LLVM opts:', opts) output = Popen([LLVM_OPT, filename] + opts + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0] assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output shutil.move(filename + '.opt.bc', filename) @@ -1148,7 +1240,7 @@ def is_ar(filename): Building._is_ar_cache[filename] = sigcheck return sigcheck except Exception, e: - if DEBUG: print >> sys.stderr, 'shared.Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e) + logging.debug('Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e)) return False @staticmethod @@ -1175,8 +1267,8 @@ def ensure_relooper(relooper): curr = os.getcwd() try: ok = False - print >> sys.stderr, '=======================================' - print >> sys.stderr, 'bootstrapping relooper...' + logging.info('=======================================') + logging.info('bootstrapping relooper...') os.chdir(path_from_root('src')) emcc_debug = os.environ.get('EMCC_DEBUG') @@ -1201,19 +1293,19 @@ def make(opt_level): f.close() # bootstrap phase 1: generate unrelooped relooper, for which we do not need a relooper (so we cannot recurse infinitely in this function) - print >> sys.stderr, ' bootstrap phase 1' + logging.info(' bootstrap phase 1') make(1) # bootstrap phase 2: generate relooped relooper, using the unrelooped relooper (we see relooper.js exists so we cannot recurse infinitely in this function) - print >> sys.stderr, ' bootstrap phase 2' + logging.info(' bootstrap phase 2') make(2) - print >> sys.stderr, 'bootstrapping relooper succeeded' - print >> sys.stderr, '=======================================' + logging.info('bootstrapping relooper succeeded') + logging.info('=======================================') ok = True finally: os.chdir(curr) if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug if not ok: - print >> sys.stderr, 'bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten' + logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten') 1/0 @staticmethod @@ -1274,7 +1366,7 @@ def execute(cmd, *args, **kw): except: if not isinstance(cmd, str): cmd = ' '.join(cmd) - print >> sys.stderr, 'Invoking Process failed: <<< ' + cmd + ' >>>' + logging.error('Invoking Process failed: <<< ' + cmd + ' >>>') raise def suffix(name): From d6a6004ff35999045f61f2f05af09f4007d60ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89loi=20Rivard?= Date: Wed, 1 May 2013 16:06:49 +0200 Subject: [PATCH 13/39] Displays usage when no argument is passed. --- emcc | 40 +++++++++++++++++++--------------------- tools/shared.py | 30 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/emcc b/emcc index 7e020a612a0dc..0b973568cc6b1 100755 --- a/emcc +++ b/emcc @@ -121,10 +121,6 @@ shared.check_sanity(force=DEBUG) # Handle some global flags -if len(sys.argv) == 1: - logging.error('no input files') - exit(1) - # read response files very early on response_file = True while response_file: @@ -138,23 +134,7 @@ while response_file: sys.argv[index:index+1] = extra_args break -if sys.argv[1] == '--version': - revision = '(unknown revision)' - here = os.getcwd() - os.chdir(shared.path_from_root()) - try: - revision = execute(['git', 'show'], stdout=PIPE, stderr=PIPE)[0].split('\n')[0] - except: - pass - finally: - os.chdir(here) - print '''emcc (Emscripten GCC-like replacement) %s (%s) -Copyright (C) 2013 the Emscripten authors (see AUTHORS.txt) -This is free and open source software under the MIT license. -There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - ''' % (shared.EMSCRIPTEN_VERSION, revision) - exit(0) -elif sys.argv[1] == '--help': +if len(sys.argv) == 1 or sys.argv[1] == '--help': this = os.path.basename('em++' if os.environ.get('EMMAKEN_CXX') else 'emcc') print '''%s [options] file... @@ -499,6 +479,24 @@ emcc: supported targets: llvm bitcode, javascript, NOT elf (autoconf likes to see elf above to enable shared object support) ''' % (this, this, this) exit(0) + +elif sys.argv[1] == '--version': + revision = '(unknown revision)' + here = os.getcwd() + os.chdir(shared.path_from_root()) + try: + revision = execute(['git', 'show'], stdout=PIPE, stderr=PIPE)[0].split('\n')[0] + except: + pass + finally: + os.chdir(here) + print '''emcc (Emscripten GCC-like replacement) %s (%s) +Copyright (C) 2013 the Emscripten authors (see AUTHORS.txt) +This is free and open source software under the MIT license. +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + ''' % (shared.EMSCRIPTEN_VERSION, revision) + exit(0) + elif len(sys.argv) == 2 and sys.argv[1] == '-v': # -v with no inputs print 'emcc (Emscripten GCC-like replacement + linker emulating GNU ld ) 2.0' exit(subprocess.call([shared.CLANG, '-v'])) diff --git a/tools/shared.py b/tools/shared.py index 97d30f0caff16..42eb50c86b7d5 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -47,7 +47,7 @@ def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, st # Call the process with fixed streams. self.process = subprocess.Popen(args, bufsize, executable, self.stdin_, self.stdout_, self.stderr_, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags) except Exception, e: - print >> sys.stderr, '\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e)) + logging.error('\nsubprocess.Popen(args=%s) failed! Exception %s\n' % (' '.join(args), str(e))) raise e def communicate(self, input=None): @@ -136,17 +136,17 @@ def new(*args): BACKGROUND_MAGENTA = 0x0050 BACKGROUND_YELLOW = 0x0060 BACKGROUND_GREY = 0x0070 - BACKGROUND_INTENSITY = 0x0080 # background color is intensified. + BACKGROUND_INTENSITY = 0x0080 # background color is intensified. levelno = args[1].levelno - if(levelno>=50): - color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY - elif(levelno>=40): + if(levelno >= 50): + color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY + elif(levelno >= 40): color = FOREGROUND_RED | FOREGROUND_INTENSITY - elif(levelno>=30): + elif(levelno >= 30): color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY - elif(levelno>=20): + elif(levelno >= 20): color = FOREGROUND_GREEN - elif(levelno>=10): + elif(levelno >= 10): color = FOREGROUND_MAGENTA else: color = FOREGROUND_WHITE @@ -161,15 +161,15 @@ def add_coloring_to_emit_ansi(fn): # add methods we need to the class def new(*args): levelno = args[1].levelno - if(levelno>=50): + if(levelno >= 50): color = '\x1b[31m' # red - elif(levelno>=40): + elif(levelno >= 40): color = '\x1b[31m' # red - elif(levelno>=30): + elif(levelno >= 30): color = '\x1b[33m' # yellow - elif(levelno>=20): - color = '\x1b[32m' # green - elif(levelno>=10): + elif(levelno >= 20): + color = '\x1b[32m' # green + elif(levelno >= 10): color = '\x1b[35m' # pink else: color = '\x1b[0m' # normal @@ -1020,7 +1020,7 @@ def llvm_as(input_filename, output_filename=None): @staticmethod def llvm_nm(filename, stdout=PIPE, stderr=None): if filename in Building.nm_cache: - #if DEBUG: print >> sys.stderr, 'loading nm results for %s from cache' % filename + #logging.debug('loading nm results for %s from cache' % filename) return Building.nm_cache[filename] # LLVM binary ==> list of symbols From ac2e339f7c33cd96da165405e8da97ead56a3fff Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 10:33:55 -0700 Subject: [PATCH 14/39] tweak some logging levels --- emcc | 4 ++-- tools/shared.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/emcc b/emcc index 0b973568cc6b1..5d63a46c312c3 100755 --- a/emcc +++ b/emcc @@ -112,7 +112,7 @@ EMCC_CFLAGS = os.environ.get('EMCC_CFLAGS') # Additional compiler flags that we logging.debug('invocation: ' + ' '.join(sys.argv) + (' + ' + EMCC_CFLAGS if EMCC_CFLAGS else '')) if EMCC_CFLAGS: sys.argv.append(EMCC_CFLAGS) -if DEBUG and LEAVE_INPUTS_RAW: logging.error('leaving inputs raw') +if DEBUG and LEAVE_INPUTS_RAW: logging.warning('leaving inputs raw') stdout = PIPE if not DEBUG else None # suppress output of child processes stderr = PIPE if not DEBUG else None # unless we are in DEBUG mode @@ -854,7 +854,7 @@ try: newargs[i] = '' elif newargs[i] == '--clear-cache': newargs[i] = '' - logging.info('clearing cache') + logging.warning('clearing cache') shared.Cache.erase() sys.exit(0) elif newargs[i] == '--save-bc': diff --git a/tools/shared.py b/tools/shared.py index 42eb50c86b7d5..f451ee30dece0 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -322,7 +322,7 @@ def check_sanity(force=False): except Exception, e: reason = 'unknown: ' + str(e) if reason: - logging.info('(Emscripten: %s, clearing cache)' % reason) + logging.warning('(Emscripten: %s, clearing cache)' % reason) Cache.erase() # some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on @@ -430,7 +430,7 @@ def __init__(self, environ): try: self.TEMP_DIR = TEMP_DIR except NameError: - logging.info('TEMP_DIR not defined in ~/.emscripten, using /tmp') + logging.debug('TEMP_DIR not defined in ~/.emscripten, using /tmp') self.TEMP_DIR = '/tmp' self.CANONICAL_TEMP_DIR = os.path.join(self.TEMP_DIR, 'emscripten_temp') From 505f5f10af17e5d9994e1840c30498d2fbda8510 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 10:41:21 -0700 Subject: [PATCH 15/39] fix some logging uses --- emcc | 6 +++--- tests/runner.py | 2 +- tools/shared.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/emcc b/emcc index 5d63a46c312c3..ad2e71ac57301 100755 --- a/emcc +++ b/emcc @@ -1359,7 +1359,7 @@ try: if len(input_files) + len(extra_files_to_link) > 1 or \ (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_SUFFIXES or suffix(temp_files[0]) in DYNAMICLIB_SUFFIXES) and shared.Building.is_ar(temp_files[0])): linker_inputs = temp_files + extra_files_to_link - logging.debug('linking: ', linker_inputs) + logging.debug('linking: ' + str(linker_inputs)) t0 = time.time() shared.Building.link(linker_inputs, in_temp(target_basename + '.bc')) t1 = time.time() @@ -1490,7 +1490,7 @@ try: if DEBUG != '2': if shared.Settings.ASM_JS: js_optimizer_queue = ['asm'] + js_optimizer_queue - logging.debug('applying js optimization passes:', js_optimizer_queue) + logging.debug('applying js optimization passes: %s', js_optimizer_queue) final = shared.Building.js_optimizer(final, js_optimizer_queue, jcache) if DEBUG: save_intermediate('js_opts') else: @@ -1498,7 +1498,7 @@ try: passes = [name] if shared.Settings.ASM_JS: passes = ['asm'] + passes - logging.info('applying js optimization pass:', passes) + logging.info('applying js optimization pass: %s', passes) final = shared.Building.js_optimizer(final, passes, jcache) save_intermediate(name) js_optimizer_queue = [] diff --git a/tests/runner.py b/tests/runner.py index d1ce2b0b53708..b94e827f7863f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -13000,7 +13000,7 @@ def test_firstrun(self): if 'LLVM_ROOT' not in settings: self.assertContained('Error in evaluating %s' % EM_CONFIG, output) elif 'runner.py' not in ' '.join(command): - self.assertContained('FATAL', output) # sanity check should fail + self.assertContained('CRITICAL', output) # sanity check should fail def test_closure_compiler(self): CLOSURE_FATAL = 'fatal: Closure compiler' diff --git a/tools/shared.py b/tools/shared.py index f451ee30dece0..8b0a26e775811 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -285,7 +285,7 @@ def check_node_version(): logging.warning('node version appears too old (seeing "%s", expected "%s")' % (actual, 'v' + ('.'.join(map(str, EXPECTED_NODE_VERSION))))) return False except Exception, e: - logging.warning('cannot check node version:' + e) + logging.warning('cannot check node version: %s', e) return False # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) @@ -925,7 +925,7 @@ def link(files, target): # Finish link actual_files = unique_ordered(actual_files) # tolerate people trying to link a.so a.so etc. - logging.debug('emcc: llvm-linking:', actual_files) + logging.debug('emcc: llvm-linking: %s', actual_files) # check for too-long command line link_cmd = [LLVM_LINK] + actual_files + ['-o', target] @@ -979,7 +979,7 @@ def llvm_opt(filename, opts): if type(opts) is int: opts = Building.pick_llvm_opts(opts) #opts += ['-debug-pass=Arguments'] - logging.debug('emcc: LLVM opts:', opts) + logging.debug('emcc: LLVM opts: ' + str(opts)) output = Popen([LLVM_OPT, filename] + opts + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0] assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output shutil.move(filename + '.opt.bc', filename) From 2cd4b8256af6611460f86c5781a233c618625488 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 10:47:23 -0700 Subject: [PATCH 16/39] restore warning on no input files, to match gcc --- emcc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/emcc b/emcc index ad2e71ac57301..44ff1684e2c7e 100755 --- a/emcc +++ b/emcc @@ -121,6 +121,10 @@ shared.check_sanity(force=DEBUG) # Handle some global flags +if len(sys.argv) == 1: + logging.warning('no input files') + exit(1) + # read response files very early on response_file = True while response_file: From af15d3e5c9dc7b4c54b75fd371f7e9b62a760826 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 10:57:16 -0700 Subject: [PATCH 17/39] update tests --- emcc | 2 +- tests/runner.py | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/emcc b/emcc index 44ff1684e2c7e..19288b77bd2ad 100755 --- a/emcc +++ b/emcc @@ -1349,7 +1349,7 @@ try: for haz in has: # remove symbols that are supplied by another of the inputs if haz in need: need.remove(haz) - logging.debug('considering including %s: we need %s and have %s' % (name, str(need), str(has))) + logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has))) if force or len(need) > 0: # We need to build and link the library in logging.debug('including %s' % name) diff --git a/tests/runner.py b/tests/runner.py index b94e827f7863f..c14197f414714 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9402,7 +9402,7 @@ def test_emcc(self): self.assertContained('error: invalid preprocessing directive', output[1]) self.assertContained(["error: use of undeclared identifier 'cheez", "error: unknown type name 'cheez'"], output[1]) self.assertContained('errors generated', output[1]) - assert 'emcc: compiler frontend failed to generate LLVM bitcode, halting' in output[1].split('errors generated.')[1] + assert 'compiler frontend failed to generate LLVM bitcode, halting' in output[1].split('errors generated.')[1] # emcc src.cpp -c and emcc src.cpp -o src.[o|bc] ==> should give a .bc file # regression check: -o js should create "js", with bitcode content @@ -9495,11 +9495,11 @@ def test_emcc(self): assert len(output[0]) == 0, output[0] if bc_params is not None: if '-O1' in params and 'something.bc' in params: - assert 'warning: -Ox flags ignored, since not generating JavaScript' in output[1] + assert '-Ox flags ignored, since not generating JavaScript' in output[1] assert os.path.exists('something.bc'), output[1] output = Popen([PYTHON, compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists('something.js'), output[1] - assert ('Warning: Applying some potentially unsafe optimizations!' in output[1]) == (opt_level >= 3), 'unsafe warning should appear in opt >= 3' + assert ('Applying some potentially unsafe optimizations!' in output[1]) == (opt_level >= 3), 'unsafe warning should appear in opt >= 3' self.assertContained('hello, world!', run_js('something.js')) # Verify optimization level etc. in the generated code @@ -9572,7 +9572,7 @@ def test_emcc(self): assert not os.path.exists(target), 'We should only have created bitcode here: ' + '\n'.join(output) # Compiling one of them alone is expected to fail - output = Popen([PYTHON, compiler, 'twopart_main.o'] + args, stdout=PIPE, stderr=PIPE).communicate() + output = Popen([PYTHON, compiler, 'twopart_main.o', '-O1', '-g'] + args, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists(target), '\n'.join(output) #print '\n'.join(output) self.assertContained('missing function', run_js(target, stderr=STDOUT)) @@ -9925,7 +9925,7 @@ def test_abspaths(self): (['-Lsubdir/something'], False), ([], False)]: err = Popen([PYTHON, EMCC, 'main.c'] + args, stderr=PIPE).communicate()[1] - assert ('emcc: warning: -I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' in err) == expected, err + assert ('-I or -L of an absolute path encountered. If this is to a local system header/library, it may cause problems (local system files make sense for compiling natively on your system, but not necessarily to JavaScript)' in err) == expected, err def test_local_link(self): # Linking a local library directly, like /usr/lib/libsomething.so, cannot work of course since it @@ -10693,7 +10693,7 @@ def test_link_s(self): Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'supp.cpp'), '-o', 'supp.o']).communicate() output = Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.o'), '-s', os.path.join(self.get_dir(), 'supp.o'), '-s', 'SAFE_HEAP=1'], stderr=PIPE).communicate() - self.assertContained('emcc: warning: treating -s as linker option', output[1]) + self.assertContained('treating -s as linker option', output[1]) output = run_js('a.out.js') assert 'yello' in output, 'code works' code = open('a.out.js').read() @@ -13004,7 +13004,7 @@ def test_firstrun(self): def test_closure_compiler(self): CLOSURE_FATAL = 'fatal: Closure compiler' - CLOSURE_WARNING = 'WARNING: Closure compiler' + CLOSURE_WARNING = 'does not exist' # Sanity check should find closure restore() @@ -13031,7 +13031,7 @@ def test_closure_compiler(self): assert os.path.exists('a.out.js'), output def test_llvm(self): - LLVM_WARNING = 'warning: LLVM version appears incorrect' + LLVM_WARNING = 'LLVM version appears incorrect' restore() @@ -13069,8 +13069,8 @@ def test_llvm(self): del os.environ['EM_IGNORE_SANITY'] def test_node(self): - NODE_WARNING = 'warning: node version appears too old' - NODE_WARNING_2 = 'warning: cannot check node version' + NODE_WARNING = 'node version appears too old' + NODE_WARNING_2 = 'cannot check node version' restore() @@ -13192,9 +13192,9 @@ def test_emcc(self): try_delete(CANONICAL_TEMP_DIR) def test_emcc_caching(self): - INCLUDING_MESSAGE = 'emcc: including X' - BUILDING_MESSAGE = 'emcc: building X for cache' - ERASING_MESSAGE = 'emcc: clearing cache' + INCLUDING_MESSAGE = 'including X' + BUILDING_MESSAGE = 'building X for cache' + ERASING_MESSAGE = 'clearing cache' EMCC_CACHE = Cache.dirname From bf6825dc530260006484db56891358bf452d4eee Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 11:46:10 -0700 Subject: [PATCH 18/39] adjust js pass logging level to debug --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index 19288b77bd2ad..584b7bca33600 100755 --- a/emcc +++ b/emcc @@ -1502,7 +1502,7 @@ try: passes = [name] if shared.Settings.ASM_JS: passes = ['asm'] + passes - logging.info('applying js optimization pass: %s', passes) + logging.debug('applying js optimization pass: %s', passes) final = shared.Building.js_optimizer(final, passes, jcache) save_intermediate(name) js_optimizer_queue = [] From c4dddc5ff1cf5939caa5d78850d6e155df92faa6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 13:14:10 -0700 Subject: [PATCH 19/39] use -fno-threadsafe-statics, issue #1128 --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 8b0a26e775811..6256ae6712147 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -506,7 +506,7 @@ def get_llvm_target(): COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__i386', '-Ui386', '-U__SSE__', '-U__SSE_MATH__', '-U__SSE2__', '-U__SSE2_MATH__', '-U__MMX__', '-DEMSCRIPTEN', '-D__EMSCRIPTEN__', '-U__STRICT_ANSI__', - '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno', + '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno', '-fno-threadsafe-statics', '-target', LLVM_TARGET] USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK') From 155342908c2dd94e433bd043367efc9799296420 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Thu, 2 May 2013 13:03:14 +0200 Subject: [PATCH 20/39] Remove executable permissions on simple files --- AUTHORS | 2 ++ emcc.py | 0 system/lib/embind/bind.cpp | 0 tests/box2d/Box2D/Box2D.h | 0 tests/box2d/Box2D/Box2DConfig.cmake | 0 tests/box2d/Box2D/CMakeLists.txt | 0 tests/box2d/Box2D/Collision/Shapes/b2ChainShape.cpp | 0 tests/box2d/Box2D/Collision/Shapes/b2ChainShape.h | 0 tests/box2d/Box2D/Collision/Shapes/b2CircleShape.cpp | 0 tests/box2d/Box2D/Collision/Shapes/b2CircleShape.h | 0 tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.cpp | 0 tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.h | 0 tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.cpp | 0 tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.h | 0 tests/box2d/Box2D/Collision/Shapes/b2Shape.h | 0 tests/box2d/Box2D/Collision/b2BroadPhase.cpp | 0 tests/box2d/Box2D/Collision/b2BroadPhase.h | 0 tests/box2d/Box2D/Collision/b2CollideCircle.cpp | 0 tests/box2d/Box2D/Collision/b2CollideEdge.cpp | 0 tests/box2d/Box2D/Collision/b2CollidePolygon.cpp | 0 tests/box2d/Box2D/Collision/b2Collision.cpp | 0 tests/box2d/Box2D/Collision/b2Collision.h | 0 tests/box2d/Box2D/Collision/b2Distance.cpp | 0 tests/box2d/Box2D/Collision/b2Distance.h | 0 tests/box2d/Box2D/Collision/b2DynamicTree.cpp | 0 tests/box2d/Box2D/Collision/b2DynamicTree.h | 0 tests/box2d/Box2D/Collision/b2TimeOfImpact.cpp | 0 tests/box2d/Box2D/Collision/b2TimeOfImpact.h | 0 tests/box2d/Box2D/Common/b2BlockAllocator.cpp | 0 tests/box2d/Box2D/Common/b2BlockAllocator.h | 0 tests/box2d/Box2D/Common/b2Draw.cpp | 0 tests/box2d/Box2D/Common/b2Draw.h | 0 tests/box2d/Box2D/Common/b2GrowableStack.h | 0 tests/box2d/Box2D/Common/b2Math.cpp | 0 tests/box2d/Box2D/Common/b2Math.h | 0 tests/box2d/Box2D/Common/b2Settings.cpp | 0 tests/box2d/Box2D/Common/b2Settings.h | 0 tests/box2d/Box2D/Common/b2StackAllocator.cpp | 0 tests/box2d/Box2D/Common/b2StackAllocator.h | 0 tests/box2d/Box2D/Common/b2Timer.cpp | 0 tests/box2d/Box2D/Common/b2Timer.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h | 0 .../box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2Contact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2Contact.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h | 0 .../box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h | 0 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.cpp | 0 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2Joint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2Joint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.h | 0 tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.cpp | 0 tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.h | 0 tests/box2d/Box2D/Dynamics/b2Body.cpp | 0 tests/box2d/Box2D/Dynamics/b2Body.h | 0 tests/box2d/Box2D/Dynamics/b2ContactManager.cpp | 0 tests/box2d/Box2D/Dynamics/b2ContactManager.h | 0 tests/box2d/Box2D/Dynamics/b2Fixture.cpp | 0 tests/box2d/Box2D/Dynamics/b2Fixture.h | 0 tests/box2d/Box2D/Dynamics/b2Island.cpp | 0 tests/box2d/Box2D/Dynamics/b2Island.h | 0 tests/box2d/Box2D/Dynamics/b2TimeStep.h | 0 tests/box2d/Box2D/Dynamics/b2World.cpp | 0 tests/box2d/Box2D/Dynamics/b2World.h | 0 tests/box2d/Box2D/Dynamics/b2WorldCallbacks.cpp | 0 tests/box2d/Box2D/Dynamics/b2WorldCallbacks.h | 0 tests/box2d/Box2D/Rope/b2Rope.cpp | 0 tests/box2d/Box2D/Rope/b2Rope.h | 0 tests/box2d/Build/Readme.txt | 0 tests/box2d/Build/vs2010/Box2D.sln | 0 tests/box2d/Build/vs2010/Box2D.vcxproj | 0 tests/box2d/Build/vs2010/Box2D.vcxproj.filters | 0 tests/box2d/Build/vs2010/FreeGLUT.vcxproj | 0 tests/box2d/Build/vs2010/FreeGLUT.vcxproj.filters | 0 tests/box2d/Build/vs2010/GLUI.vcxproj | 0 tests/box2d/Build/vs2010/GLUI.vcxproj.filters | 0 tests/box2d/Build/vs2010/HelloWorld.vcxproj | 0 tests/box2d/Build/vs2010/HelloWorld.vcxproj.filters | 0 tests/box2d/Build/vs2010/Testbed.vcxproj | 0 tests/box2d/Build/vs2010/Testbed.vcxproj.filters | 0 tests/box2d/Build/xcode4/Box2D.xcodeproj/project.pbxproj | 0 .../project.xcworkspace/contents.xcworkspacedata | 0 tests/box2d/Building.txt | 0 tests/box2d/CMakeLists.txt | 0 tests/box2d/HelloWorld/CMakeLists.txt | 0 tests/box2d/HelloWorld/HelloWorld.cpp | 0 tests/box2d/License.txt | 0 tests/box2d/Readme.txt | 0 tests/box2d/Testbed/CMakeLists.txt | 0 tests/box2d/Testbed/Framework/Main.cpp | 0 tests/box2d/Testbed/Framework/Render.cpp | 0 tests/box2d/Testbed/Framework/Render.h | 0 tests/box2d/Testbed/Framework/Test.cpp | 0 tests/box2d/Testbed/Framework/Test.h | 0 tests/box2d/Testbed/Tests/AddPair.h | 0 tests/box2d/Testbed/Tests/ApplyForce.h | 0 tests/box2d/Testbed/Tests/BodyTypes.h | 0 tests/box2d/Testbed/Tests/Breakable.h | 0 tests/box2d/Testbed/Tests/Bridge.h | 0 tests/box2d/Testbed/Tests/BulletTest.h | 0 tests/box2d/Testbed/Tests/Cantilever.h | 0 tests/box2d/Testbed/Tests/Car.h | 0 tests/box2d/Testbed/Tests/Chain.h | 0 tests/box2d/Testbed/Tests/CharacterCollision.h | 0 tests/box2d/Testbed/Tests/CollisionFiltering.h | 0 tests/box2d/Testbed/Tests/CollisionProcessing.h | 0 tests/box2d/Testbed/Tests/CompoundShapes.h | 0 tests/box2d/Testbed/Tests/Confined.h | 0 tests/box2d/Testbed/Tests/ContinuousTest.h | 0 tests/box2d/Testbed/Tests/DistanceTest.h | 0 tests/box2d/Testbed/Tests/Dominos.h | 0 tests/box2d/Testbed/Tests/DumpShell.h | 0 tests/box2d/Testbed/Tests/DynamicTreeTest.h | 0 tests/box2d/Testbed/Tests/EdgeShapes.h | 0 tests/box2d/Testbed/Tests/EdgeTest.h | 0 tests/box2d/Testbed/Tests/Gears.h | 0 tests/box2d/Testbed/Tests/OneSidedPlatform.h | 0 tests/box2d/Testbed/Tests/Pinball.h | 0 tests/box2d/Testbed/Tests/PolyCollision.h | 0 tests/box2d/Testbed/Tests/PolyShapes.h | 0 tests/box2d/Testbed/Tests/Prismatic.h | 0 tests/box2d/Testbed/Tests/Pulleys.h | 0 tests/box2d/Testbed/Tests/Pyramid.h | 0 tests/box2d/Testbed/Tests/RayCast.h | 0 tests/box2d/Testbed/Tests/Revolute.h | 0 tests/box2d/Testbed/Tests/Rope.h | 0 tests/box2d/Testbed/Tests/RopeJoint.h | 0 tests/box2d/Testbed/Tests/SensorTest.h | 0 tests/box2d/Testbed/Tests/ShapeEditing.h | 0 tests/box2d/Testbed/Tests/SliderCrank.h | 0 tests/box2d/Testbed/Tests/SphereStack.h | 0 tests/box2d/Testbed/Tests/TestEntries.cpp | 0 tests/box2d/Testbed/Tests/TheoJansen.h | 0 tests/box2d/Testbed/Tests/Tiles.h | 0 tests/box2d/Testbed/Tests/TimeOfImpact.h | 0 tests/box2d/Testbed/Tests/Tumbler.h | 0 tests/box2d/Testbed/Tests/VaryingFriction.h | 0 tests/box2d/Testbed/Tests/VaryingRestitution.h | 0 tests/box2d/Testbed/Tests/VerticalStack.h | 0 tests/box2d/Testbed/Tests/Web.h | 0 tests/box2d/freeglut/CMakeLists.txt | 0 tests/box2d/freeglut/COPYING | 0 tests/box2d/freeglut/freeglut.h | 0 tests/box2d/freeglut/freeglut_callbacks.c | 0 tests/box2d/freeglut/freeglut_cursor.c | 0 tests/box2d/freeglut/freeglut_display.c | 0 tests/box2d/freeglut/freeglut_ext.c | 0 tests/box2d/freeglut/freeglut_ext.h | 0 tests/box2d/freeglut/freeglut_font.c | 0 tests/box2d/freeglut/freeglut_font_data.c | 0 tests/box2d/freeglut/freeglut_gamemode.c | 0 tests/box2d/freeglut/freeglut_geometry.c | 0 tests/box2d/freeglut/freeglut_glutfont_definitions.c | 0 tests/box2d/freeglut/freeglut_init.c | 0 tests/box2d/freeglut/freeglut_input_devices.c | 0 tests/box2d/freeglut/freeglut_internal.h | 0 tests/box2d/freeglut/freeglut_joystick.c | 0 tests/box2d/freeglut/freeglut_main.c | 0 tests/box2d/freeglut/freeglut_menu.c | 0 tests/box2d/freeglut/freeglut_misc.c | 0 tests/box2d/freeglut/freeglut_overlay.c | 0 tests/box2d/freeglut/freeglut_spaceball.c | 0 tests/box2d/freeglut/freeglut_state.c | 0 tests/box2d/freeglut/freeglut_std.h | 0 tests/box2d/freeglut/freeglut_stroke_mono_roman.c | 0 tests/box2d/freeglut/freeglut_stroke_roman.c | 0 tests/box2d/freeglut/freeglut_structure.c | 0 tests/box2d/freeglut/freeglut_teapot.c | 0 tests/box2d/freeglut/freeglut_teapot_data.h | 0 tests/box2d/freeglut/freeglut_videoresize.c | 0 tests/box2d/freeglut/freeglut_window.c | 0 tests/box2d/glui/CMakeLists.txt | 0 tests/box2d/glui/algebra3.cpp | 0 tests/box2d/glui/algebra3.h | 0 tests/box2d/glui/arcball.cpp | 0 tests/box2d/glui/arcball.h | 0 tests/box2d/glui/glui.cpp | 0 tests/box2d/glui/glui.h | 0 tests/box2d/glui/glui_add_controls.cpp | 0 tests/box2d/glui/glui_bitmap_img_data.cpp | 0 tests/box2d/glui/glui_bitmaps.cpp | 0 tests/box2d/glui/glui_button.cpp | 0 tests/box2d/glui/glui_checkbox.cpp | 0 tests/box2d/glui/glui_column.cpp | 0 tests/box2d/glui/glui_commandline.cpp | 0 tests/box2d/glui/glui_control.cpp | 0 tests/box2d/glui/glui_edittext.cpp | 0 tests/box2d/glui/glui_filebrowser.cpp | 0 tests/box2d/glui/glui_internal.h | 0 tests/box2d/glui/glui_internal_control.h | 0 tests/box2d/glui/glui_list.cpp | 0 tests/box2d/glui/glui_listbox.cpp | 0 tests/box2d/glui/glui_mouse_iaction.cpp | 0 tests/box2d/glui/glui_node.cpp | 0 tests/box2d/glui/glui_panel.cpp | 0 tests/box2d/glui/glui_radio.cpp | 0 tests/box2d/glui/glui_rollout.cpp | 0 tests/box2d/glui/glui_rotation.cpp | 0 tests/box2d/glui/glui_scrollbar.cpp | 0 tests/box2d/glui/glui_separator.cpp | 0 tests/box2d/glui/glui_spinner.cpp | 0 tests/box2d/glui/glui_statictext.cpp | 0 tests/box2d/glui/glui_string.cpp | 0 tests/box2d/glui/glui_textbox.cpp | 0 tests/box2d/glui/glui_translation.cpp | 0 tests/box2d/glui/glui_tree.cpp | 0 tests/box2d/glui/glui_treepanel.cpp | 0 tests/box2d/glui/glui_window.cpp | 0 tests/box2d/glui/quaternion.cpp | 0 tests/box2d/glui/quaternion.h | 0 tests/box2d/glui/readme.txt | 0 tests/box2d/premake4.lua | 0 .../src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp | 0 .../src/BulletDynamics/ConstraintSolver/btSliderConstraint.h | 0 tests/bullet/src/LinearMath/btPoolAllocator.h | 0 tests/poppler/goo/GooTimer.h | 0 tools/split.py | 0 245 files changed, 2 insertions(+) mode change 100755 => 100644 emcc.py mode change 100755 => 100644 system/lib/embind/bind.cpp mode change 100755 => 100644 tests/box2d/Box2D/Box2D.h mode change 100755 => 100644 tests/box2d/Box2D/Box2DConfig.cmake mode change 100755 => 100644 tests/box2d/Box2D/CMakeLists.txt mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2ChainShape.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2ChainShape.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2CircleShape.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2CircleShape.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/Shapes/b2Shape.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2BroadPhase.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2BroadPhase.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2CollideCircle.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2CollideEdge.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2CollidePolygon.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2Collision.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2Collision.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2Distance.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2Distance.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2DynamicTree.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2DynamicTree.h mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2TimeOfImpact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Collision/b2TimeOfImpact.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2BlockAllocator.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2BlockAllocator.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Draw.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Draw.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2GrowableStack.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Math.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Math.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Settings.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Settings.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2StackAllocator.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2StackAllocator.h mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Timer.cpp mode change 100755 => 100644 tests/box2d/Box2D/Common/b2Timer.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2Contact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2Contact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2Joint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2Joint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Body.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Body.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2ContactManager.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2ContactManager.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Fixture.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Fixture.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Island.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2Island.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2TimeStep.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2World.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2World.h mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2WorldCallbacks.cpp mode change 100755 => 100644 tests/box2d/Box2D/Dynamics/b2WorldCallbacks.h mode change 100755 => 100644 tests/box2d/Box2D/Rope/b2Rope.cpp mode change 100755 => 100644 tests/box2d/Box2D/Rope/b2Rope.h mode change 100755 => 100644 tests/box2d/Build/Readme.txt mode change 100755 => 100644 tests/box2d/Build/vs2010/Box2D.sln mode change 100755 => 100644 tests/box2d/Build/vs2010/Box2D.vcxproj mode change 100755 => 100644 tests/box2d/Build/vs2010/Box2D.vcxproj.filters mode change 100755 => 100644 tests/box2d/Build/vs2010/FreeGLUT.vcxproj mode change 100755 => 100644 tests/box2d/Build/vs2010/FreeGLUT.vcxproj.filters mode change 100755 => 100644 tests/box2d/Build/vs2010/GLUI.vcxproj mode change 100755 => 100644 tests/box2d/Build/vs2010/GLUI.vcxproj.filters mode change 100755 => 100644 tests/box2d/Build/vs2010/HelloWorld.vcxproj mode change 100755 => 100644 tests/box2d/Build/vs2010/HelloWorld.vcxproj.filters mode change 100755 => 100644 tests/box2d/Build/vs2010/Testbed.vcxproj mode change 100755 => 100644 tests/box2d/Build/vs2010/Testbed.vcxproj.filters mode change 100755 => 100644 tests/box2d/Build/xcode4/Box2D.xcodeproj/project.pbxproj mode change 100755 => 100644 tests/box2d/Build/xcode4/Box2D.xcodeproj/project.xcworkspace/contents.xcworkspacedata mode change 100755 => 100644 tests/box2d/Building.txt mode change 100755 => 100644 tests/box2d/CMakeLists.txt mode change 100755 => 100644 tests/box2d/HelloWorld/CMakeLists.txt mode change 100755 => 100644 tests/box2d/HelloWorld/HelloWorld.cpp mode change 100755 => 100644 tests/box2d/License.txt mode change 100755 => 100644 tests/box2d/Readme.txt mode change 100755 => 100644 tests/box2d/Testbed/CMakeLists.txt mode change 100755 => 100644 tests/box2d/Testbed/Framework/Main.cpp mode change 100755 => 100644 tests/box2d/Testbed/Framework/Render.cpp mode change 100755 => 100644 tests/box2d/Testbed/Framework/Render.h mode change 100755 => 100644 tests/box2d/Testbed/Framework/Test.cpp mode change 100755 => 100644 tests/box2d/Testbed/Framework/Test.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/AddPair.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/ApplyForce.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/BodyTypes.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Breakable.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Bridge.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/BulletTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Cantilever.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Car.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Chain.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/CharacterCollision.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/CollisionFiltering.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/CollisionProcessing.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/CompoundShapes.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Confined.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/ContinuousTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/DistanceTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Dominos.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/DumpShell.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/DynamicTreeTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/EdgeShapes.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/EdgeTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Gears.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/OneSidedPlatform.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Pinball.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/PolyCollision.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/PolyShapes.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Prismatic.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Pulleys.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Pyramid.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/RayCast.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Revolute.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Rope.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/RopeJoint.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/SensorTest.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/ShapeEditing.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/SliderCrank.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/SphereStack.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/TestEntries.cpp mode change 100755 => 100644 tests/box2d/Testbed/Tests/TheoJansen.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Tiles.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/TimeOfImpact.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Tumbler.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/VaryingFriction.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/VaryingRestitution.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/VerticalStack.h mode change 100755 => 100644 tests/box2d/Testbed/Tests/Web.h mode change 100755 => 100644 tests/box2d/freeglut/CMakeLists.txt mode change 100755 => 100644 tests/box2d/freeglut/COPYING mode change 100755 => 100644 tests/box2d/freeglut/freeglut.h mode change 100755 => 100644 tests/box2d/freeglut/freeglut_callbacks.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_cursor.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_display.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_ext.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_ext.h mode change 100755 => 100644 tests/box2d/freeglut/freeglut_font.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_font_data.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_gamemode.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_geometry.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_glutfont_definitions.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_init.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_input_devices.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_internal.h mode change 100755 => 100644 tests/box2d/freeglut/freeglut_joystick.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_main.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_menu.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_misc.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_overlay.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_spaceball.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_state.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_std.h mode change 100755 => 100644 tests/box2d/freeglut/freeglut_stroke_mono_roman.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_stroke_roman.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_structure.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_teapot.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_teapot_data.h mode change 100755 => 100644 tests/box2d/freeglut/freeglut_videoresize.c mode change 100755 => 100644 tests/box2d/freeglut/freeglut_window.c mode change 100755 => 100644 tests/box2d/glui/CMakeLists.txt mode change 100755 => 100644 tests/box2d/glui/algebra3.cpp mode change 100755 => 100644 tests/box2d/glui/algebra3.h mode change 100755 => 100644 tests/box2d/glui/arcball.cpp mode change 100755 => 100644 tests/box2d/glui/arcball.h mode change 100755 => 100644 tests/box2d/glui/glui.cpp mode change 100755 => 100644 tests/box2d/glui/glui.h mode change 100755 => 100644 tests/box2d/glui/glui_add_controls.cpp mode change 100755 => 100644 tests/box2d/glui/glui_bitmap_img_data.cpp mode change 100755 => 100644 tests/box2d/glui/glui_bitmaps.cpp mode change 100755 => 100644 tests/box2d/glui/glui_button.cpp mode change 100755 => 100644 tests/box2d/glui/glui_checkbox.cpp mode change 100755 => 100644 tests/box2d/glui/glui_column.cpp mode change 100755 => 100644 tests/box2d/glui/glui_commandline.cpp mode change 100755 => 100644 tests/box2d/glui/glui_control.cpp mode change 100755 => 100644 tests/box2d/glui/glui_edittext.cpp mode change 100755 => 100644 tests/box2d/glui/glui_filebrowser.cpp mode change 100755 => 100644 tests/box2d/glui/glui_internal.h mode change 100755 => 100644 tests/box2d/glui/glui_internal_control.h mode change 100755 => 100644 tests/box2d/glui/glui_list.cpp mode change 100755 => 100644 tests/box2d/glui/glui_listbox.cpp mode change 100755 => 100644 tests/box2d/glui/glui_mouse_iaction.cpp mode change 100755 => 100644 tests/box2d/glui/glui_node.cpp mode change 100755 => 100644 tests/box2d/glui/glui_panel.cpp mode change 100755 => 100644 tests/box2d/glui/glui_radio.cpp mode change 100755 => 100644 tests/box2d/glui/glui_rollout.cpp mode change 100755 => 100644 tests/box2d/glui/glui_rotation.cpp mode change 100755 => 100644 tests/box2d/glui/glui_scrollbar.cpp mode change 100755 => 100644 tests/box2d/glui/glui_separator.cpp mode change 100755 => 100644 tests/box2d/glui/glui_spinner.cpp mode change 100755 => 100644 tests/box2d/glui/glui_statictext.cpp mode change 100755 => 100644 tests/box2d/glui/glui_string.cpp mode change 100755 => 100644 tests/box2d/glui/glui_textbox.cpp mode change 100755 => 100644 tests/box2d/glui/glui_translation.cpp mode change 100755 => 100644 tests/box2d/glui/glui_tree.cpp mode change 100755 => 100644 tests/box2d/glui/glui_treepanel.cpp mode change 100755 => 100644 tests/box2d/glui/glui_window.cpp mode change 100755 => 100644 tests/box2d/glui/quaternion.cpp mode change 100755 => 100644 tests/box2d/glui/quaternion.h mode change 100755 => 100644 tests/box2d/glui/readme.txt mode change 100755 => 100644 tests/box2d/premake4.lua mode change 100755 => 100644 tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp mode change 100755 => 100644 tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h mode change 100755 => 100644 tests/bullet/src/LinearMath/btPoolAllocator.h mode change 100755 => 100644 tests/poppler/goo/GooTimer.h mode change 100755 => 100644 tools/split.py diff --git a/AUTHORS b/AUTHORS index 43ea83ddc5102..16753be4f6fb3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -70,3 +70,5 @@ a license to everyone to use it as detailed in LICENSE.) * Todd Lee (copyright owned by IMVU) * Anthony Pesch * Robert Bragg (copyright owned by Intel Corporation) +* Sylvestre Ledru + diff --git a/emcc.py b/emcc.py old mode 100755 new mode 100644 diff --git a/system/lib/embind/bind.cpp b/system/lib/embind/bind.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Box2D.h b/tests/box2d/Box2D/Box2D.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Box2DConfig.cmake b/tests/box2d/Box2D/Box2DConfig.cmake old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/CMakeLists.txt b/tests/box2d/Box2D/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2ChainShape.cpp b/tests/box2d/Box2D/Collision/Shapes/b2ChainShape.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2ChainShape.h b/tests/box2d/Box2D/Collision/Shapes/b2ChainShape.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2CircleShape.cpp b/tests/box2d/Box2D/Collision/Shapes/b2CircleShape.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2CircleShape.h b/tests/box2d/Box2D/Collision/Shapes/b2CircleShape.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.cpp b/tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.h b/tests/box2d/Box2D/Collision/Shapes/b2EdgeShape.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.cpp b/tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.h b/tests/box2d/Box2D/Collision/Shapes/b2PolygonShape.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/Shapes/b2Shape.h b/tests/box2d/Box2D/Collision/Shapes/b2Shape.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2BroadPhase.cpp b/tests/box2d/Box2D/Collision/b2BroadPhase.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2BroadPhase.h b/tests/box2d/Box2D/Collision/b2BroadPhase.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2CollideCircle.cpp b/tests/box2d/Box2D/Collision/b2CollideCircle.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2CollideEdge.cpp b/tests/box2d/Box2D/Collision/b2CollideEdge.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2CollidePolygon.cpp b/tests/box2d/Box2D/Collision/b2CollidePolygon.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2Collision.cpp b/tests/box2d/Box2D/Collision/b2Collision.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2Collision.h b/tests/box2d/Box2D/Collision/b2Collision.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2Distance.cpp b/tests/box2d/Box2D/Collision/b2Distance.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2Distance.h b/tests/box2d/Box2D/Collision/b2Distance.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2DynamicTree.cpp b/tests/box2d/Box2D/Collision/b2DynamicTree.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2DynamicTree.h b/tests/box2d/Box2D/Collision/b2DynamicTree.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2TimeOfImpact.cpp b/tests/box2d/Box2D/Collision/b2TimeOfImpact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Collision/b2TimeOfImpact.h b/tests/box2d/Box2D/Collision/b2TimeOfImpact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2BlockAllocator.cpp b/tests/box2d/Box2D/Common/b2BlockAllocator.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2BlockAllocator.h b/tests/box2d/Box2D/Common/b2BlockAllocator.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Draw.cpp b/tests/box2d/Box2D/Common/b2Draw.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Draw.h b/tests/box2d/Box2D/Common/b2Draw.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2GrowableStack.h b/tests/box2d/Box2D/Common/b2GrowableStack.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Math.cpp b/tests/box2d/Box2D/Common/b2Math.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Math.h b/tests/box2d/Box2D/Common/b2Math.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Settings.cpp b/tests/box2d/Box2D/Common/b2Settings.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Settings.h b/tests/box2d/Box2D/Common/b2Settings.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2StackAllocator.cpp b/tests/box2d/Box2D/Common/b2StackAllocator.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2StackAllocator.h b/tests/box2d/Box2D/Common/b2StackAllocator.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Timer.cpp b/tests/box2d/Box2D/Common/b2Timer.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Common/b2Timer.h b/tests/box2d/Box2D/Common/b2Timer.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndCircleContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2ChainAndPolygonContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2CircleContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2Contact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2Contact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2Contact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2Contact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.h b/tests/box2d/Box2D/Dynamics/Contacts/b2ContactSolver.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndCircleContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2EdgeAndPolygonContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.cpp b/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.h b/tests/box2d/Box2D/Dynamics/Contacts/b2PolygonContact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2DistanceJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2FrictionJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2GearJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2Joint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2Joint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2Joint.h b/tests/box2d/Box2D/Dynamics/Joints/b2Joint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2MouseJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2PrismaticJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2PulleyJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2RevoluteJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2RopeJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2WeldJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.cpp b/tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.h b/tests/box2d/Box2D/Dynamics/Joints/b2WheelJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Body.cpp b/tests/box2d/Box2D/Dynamics/b2Body.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Body.h b/tests/box2d/Box2D/Dynamics/b2Body.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2ContactManager.cpp b/tests/box2d/Box2D/Dynamics/b2ContactManager.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2ContactManager.h b/tests/box2d/Box2D/Dynamics/b2ContactManager.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Fixture.cpp b/tests/box2d/Box2D/Dynamics/b2Fixture.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Fixture.h b/tests/box2d/Box2D/Dynamics/b2Fixture.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Island.cpp b/tests/box2d/Box2D/Dynamics/b2Island.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2Island.h b/tests/box2d/Box2D/Dynamics/b2Island.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2TimeStep.h b/tests/box2d/Box2D/Dynamics/b2TimeStep.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2World.cpp b/tests/box2d/Box2D/Dynamics/b2World.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2World.h b/tests/box2d/Box2D/Dynamics/b2World.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2WorldCallbacks.cpp b/tests/box2d/Box2D/Dynamics/b2WorldCallbacks.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Dynamics/b2WorldCallbacks.h b/tests/box2d/Box2D/Dynamics/b2WorldCallbacks.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Rope/b2Rope.cpp b/tests/box2d/Box2D/Rope/b2Rope.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Box2D/Rope/b2Rope.h b/tests/box2d/Box2D/Rope/b2Rope.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/Readme.txt b/tests/box2d/Build/Readme.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/Box2D.sln b/tests/box2d/Build/vs2010/Box2D.sln old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/Box2D.vcxproj b/tests/box2d/Build/vs2010/Box2D.vcxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/Box2D.vcxproj.filters b/tests/box2d/Build/vs2010/Box2D.vcxproj.filters old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/FreeGLUT.vcxproj b/tests/box2d/Build/vs2010/FreeGLUT.vcxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/FreeGLUT.vcxproj.filters b/tests/box2d/Build/vs2010/FreeGLUT.vcxproj.filters old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/GLUI.vcxproj b/tests/box2d/Build/vs2010/GLUI.vcxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/GLUI.vcxproj.filters b/tests/box2d/Build/vs2010/GLUI.vcxproj.filters old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/HelloWorld.vcxproj b/tests/box2d/Build/vs2010/HelloWorld.vcxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/HelloWorld.vcxproj.filters b/tests/box2d/Build/vs2010/HelloWorld.vcxproj.filters old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/Testbed.vcxproj b/tests/box2d/Build/vs2010/Testbed.vcxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/vs2010/Testbed.vcxproj.filters b/tests/box2d/Build/vs2010/Testbed.vcxproj.filters old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/xcode4/Box2D.xcodeproj/project.pbxproj b/tests/box2d/Build/xcode4/Box2D.xcodeproj/project.pbxproj old mode 100755 new mode 100644 diff --git a/tests/box2d/Build/xcode4/Box2D.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/tests/box2d/Build/xcode4/Box2D.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100755 new mode 100644 diff --git a/tests/box2d/Building.txt b/tests/box2d/Building.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/CMakeLists.txt b/tests/box2d/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/HelloWorld/CMakeLists.txt b/tests/box2d/HelloWorld/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/HelloWorld/HelloWorld.cpp b/tests/box2d/HelloWorld/HelloWorld.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/License.txt b/tests/box2d/License.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/Readme.txt b/tests/box2d/Readme.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/CMakeLists.txt b/tests/box2d/Testbed/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Framework/Main.cpp b/tests/box2d/Testbed/Framework/Main.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Framework/Render.cpp b/tests/box2d/Testbed/Framework/Render.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Framework/Render.h b/tests/box2d/Testbed/Framework/Render.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Framework/Test.cpp b/tests/box2d/Testbed/Framework/Test.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Framework/Test.h b/tests/box2d/Testbed/Framework/Test.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/AddPair.h b/tests/box2d/Testbed/Tests/AddPair.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/ApplyForce.h b/tests/box2d/Testbed/Tests/ApplyForce.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/BodyTypes.h b/tests/box2d/Testbed/Tests/BodyTypes.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Breakable.h b/tests/box2d/Testbed/Tests/Breakable.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Bridge.h b/tests/box2d/Testbed/Tests/Bridge.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/BulletTest.h b/tests/box2d/Testbed/Tests/BulletTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Cantilever.h b/tests/box2d/Testbed/Tests/Cantilever.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Car.h b/tests/box2d/Testbed/Tests/Car.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Chain.h b/tests/box2d/Testbed/Tests/Chain.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/CharacterCollision.h b/tests/box2d/Testbed/Tests/CharacterCollision.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/CollisionFiltering.h b/tests/box2d/Testbed/Tests/CollisionFiltering.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/CollisionProcessing.h b/tests/box2d/Testbed/Tests/CollisionProcessing.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/CompoundShapes.h b/tests/box2d/Testbed/Tests/CompoundShapes.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Confined.h b/tests/box2d/Testbed/Tests/Confined.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/ContinuousTest.h b/tests/box2d/Testbed/Tests/ContinuousTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/DistanceTest.h b/tests/box2d/Testbed/Tests/DistanceTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Dominos.h b/tests/box2d/Testbed/Tests/Dominos.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/DumpShell.h b/tests/box2d/Testbed/Tests/DumpShell.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/DynamicTreeTest.h b/tests/box2d/Testbed/Tests/DynamicTreeTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/EdgeShapes.h b/tests/box2d/Testbed/Tests/EdgeShapes.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/EdgeTest.h b/tests/box2d/Testbed/Tests/EdgeTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Gears.h b/tests/box2d/Testbed/Tests/Gears.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/OneSidedPlatform.h b/tests/box2d/Testbed/Tests/OneSidedPlatform.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Pinball.h b/tests/box2d/Testbed/Tests/Pinball.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/PolyCollision.h b/tests/box2d/Testbed/Tests/PolyCollision.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/PolyShapes.h b/tests/box2d/Testbed/Tests/PolyShapes.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Prismatic.h b/tests/box2d/Testbed/Tests/Prismatic.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Pulleys.h b/tests/box2d/Testbed/Tests/Pulleys.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Pyramid.h b/tests/box2d/Testbed/Tests/Pyramid.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/RayCast.h b/tests/box2d/Testbed/Tests/RayCast.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Revolute.h b/tests/box2d/Testbed/Tests/Revolute.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Rope.h b/tests/box2d/Testbed/Tests/Rope.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/RopeJoint.h b/tests/box2d/Testbed/Tests/RopeJoint.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/SensorTest.h b/tests/box2d/Testbed/Tests/SensorTest.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/ShapeEditing.h b/tests/box2d/Testbed/Tests/ShapeEditing.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/SliderCrank.h b/tests/box2d/Testbed/Tests/SliderCrank.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/SphereStack.h b/tests/box2d/Testbed/Tests/SphereStack.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/TestEntries.cpp b/tests/box2d/Testbed/Tests/TestEntries.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/TheoJansen.h b/tests/box2d/Testbed/Tests/TheoJansen.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Tiles.h b/tests/box2d/Testbed/Tests/Tiles.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/TimeOfImpact.h b/tests/box2d/Testbed/Tests/TimeOfImpact.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Tumbler.h b/tests/box2d/Testbed/Tests/Tumbler.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/VaryingFriction.h b/tests/box2d/Testbed/Tests/VaryingFriction.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/VaryingRestitution.h b/tests/box2d/Testbed/Tests/VaryingRestitution.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/VerticalStack.h b/tests/box2d/Testbed/Tests/VerticalStack.h old mode 100755 new mode 100644 diff --git a/tests/box2d/Testbed/Tests/Web.h b/tests/box2d/Testbed/Tests/Web.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/CMakeLists.txt b/tests/box2d/freeglut/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/COPYING b/tests/box2d/freeglut/COPYING old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut.h b/tests/box2d/freeglut/freeglut.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_callbacks.c b/tests/box2d/freeglut/freeglut_callbacks.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_cursor.c b/tests/box2d/freeglut/freeglut_cursor.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_display.c b/tests/box2d/freeglut/freeglut_display.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_ext.c b/tests/box2d/freeglut/freeglut_ext.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_ext.h b/tests/box2d/freeglut/freeglut_ext.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_font.c b/tests/box2d/freeglut/freeglut_font.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_font_data.c b/tests/box2d/freeglut/freeglut_font_data.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_gamemode.c b/tests/box2d/freeglut/freeglut_gamemode.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_geometry.c b/tests/box2d/freeglut/freeglut_geometry.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_glutfont_definitions.c b/tests/box2d/freeglut/freeglut_glutfont_definitions.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_init.c b/tests/box2d/freeglut/freeglut_init.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_input_devices.c b/tests/box2d/freeglut/freeglut_input_devices.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_internal.h b/tests/box2d/freeglut/freeglut_internal.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_joystick.c b/tests/box2d/freeglut/freeglut_joystick.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_main.c b/tests/box2d/freeglut/freeglut_main.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_menu.c b/tests/box2d/freeglut/freeglut_menu.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_misc.c b/tests/box2d/freeglut/freeglut_misc.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_overlay.c b/tests/box2d/freeglut/freeglut_overlay.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_spaceball.c b/tests/box2d/freeglut/freeglut_spaceball.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_state.c b/tests/box2d/freeglut/freeglut_state.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_std.h b/tests/box2d/freeglut/freeglut_std.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_stroke_mono_roman.c b/tests/box2d/freeglut/freeglut_stroke_mono_roman.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_stroke_roman.c b/tests/box2d/freeglut/freeglut_stroke_roman.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_structure.c b/tests/box2d/freeglut/freeglut_structure.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_teapot.c b/tests/box2d/freeglut/freeglut_teapot.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_teapot_data.h b/tests/box2d/freeglut/freeglut_teapot_data.h old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_videoresize.c b/tests/box2d/freeglut/freeglut_videoresize.c old mode 100755 new mode 100644 diff --git a/tests/box2d/freeglut/freeglut_window.c b/tests/box2d/freeglut/freeglut_window.c old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/CMakeLists.txt b/tests/box2d/glui/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/algebra3.cpp b/tests/box2d/glui/algebra3.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/algebra3.h b/tests/box2d/glui/algebra3.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/arcball.cpp b/tests/box2d/glui/arcball.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/arcball.h b/tests/box2d/glui/arcball.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui.cpp b/tests/box2d/glui/glui.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui.h b/tests/box2d/glui/glui.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_add_controls.cpp b/tests/box2d/glui/glui_add_controls.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_bitmap_img_data.cpp b/tests/box2d/glui/glui_bitmap_img_data.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_bitmaps.cpp b/tests/box2d/glui/glui_bitmaps.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_button.cpp b/tests/box2d/glui/glui_button.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_checkbox.cpp b/tests/box2d/glui/glui_checkbox.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_column.cpp b/tests/box2d/glui/glui_column.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_commandline.cpp b/tests/box2d/glui/glui_commandline.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_control.cpp b/tests/box2d/glui/glui_control.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_edittext.cpp b/tests/box2d/glui/glui_edittext.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_filebrowser.cpp b/tests/box2d/glui/glui_filebrowser.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_internal.h b/tests/box2d/glui/glui_internal.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_internal_control.h b/tests/box2d/glui/glui_internal_control.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_list.cpp b/tests/box2d/glui/glui_list.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_listbox.cpp b/tests/box2d/glui/glui_listbox.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_mouse_iaction.cpp b/tests/box2d/glui/glui_mouse_iaction.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_node.cpp b/tests/box2d/glui/glui_node.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_panel.cpp b/tests/box2d/glui/glui_panel.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_radio.cpp b/tests/box2d/glui/glui_radio.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_rollout.cpp b/tests/box2d/glui/glui_rollout.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_rotation.cpp b/tests/box2d/glui/glui_rotation.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_scrollbar.cpp b/tests/box2d/glui/glui_scrollbar.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_separator.cpp b/tests/box2d/glui/glui_separator.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_spinner.cpp b/tests/box2d/glui/glui_spinner.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_statictext.cpp b/tests/box2d/glui/glui_statictext.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_string.cpp b/tests/box2d/glui/glui_string.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_textbox.cpp b/tests/box2d/glui/glui_textbox.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_translation.cpp b/tests/box2d/glui/glui_translation.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_tree.cpp b/tests/box2d/glui/glui_tree.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_treepanel.cpp b/tests/box2d/glui/glui_treepanel.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/glui_window.cpp b/tests/box2d/glui/glui_window.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/quaternion.cpp b/tests/box2d/glui/quaternion.cpp old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/quaternion.h b/tests/box2d/glui/quaternion.h old mode 100755 new mode 100644 diff --git a/tests/box2d/glui/readme.txt b/tests/box2d/glui/readme.txt old mode 100755 new mode 100644 diff --git a/tests/box2d/premake4.lua b/tests/box2d/premake4.lua old mode 100755 new mode 100644 diff --git a/tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp old mode 100755 new mode 100644 diff --git a/tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/tests/bullet/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h old mode 100755 new mode 100644 diff --git a/tests/bullet/src/LinearMath/btPoolAllocator.h b/tests/bullet/src/LinearMath/btPoolAllocator.h old mode 100755 new mode 100644 diff --git a/tests/poppler/goo/GooTimer.h b/tests/poppler/goo/GooTimer.h old mode 100755 new mode 100644 diff --git a/tools/split.py b/tools/split.py old mode 100755 new mode 100644 From cac435e8aad60b535d3abdc648f97837a037a573 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 3 May 2013 16:54:19 +0200 Subject: [PATCH 21/39] Provide the right declarations for the scripts to be executed correctly --- src/relooper/doit.sh | 2 ++ src/relooper/testit.sh | 2 ++ src/relooper/updateit.sh | 1 + 3 files changed, 5 insertions(+) diff --git a/src/relooper/doit.sh b/src/relooper/doit.sh index bf2683d57a6a0..5a55dd7994558 100755 --- a/src/relooper/doit.sh +++ b/src/relooper/doit.sh @@ -1,3 +1,5 @@ +#!/bin/sh + echo "relooper" g++ Relooper.cpp -c -g g++ Relooper.cpp -c -g -DDEBUG -o RelooperDebug.o diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh index 28413c0de545c..61e1a2fb73c38 100755 --- a/src/relooper/testit.sh +++ b/src/relooper/testit.sh @@ -1,3 +1,5 @@ +#!/bin/sh + echo "test" ./test &> test.out diff -U 5 test.txt test.out diff --git a/src/relooper/updateit.sh b/src/relooper/updateit.sh index 91ccd3ab2c024..8c434753d2375 100755 --- a/src/relooper/updateit.sh +++ b/src/relooper/updateit.sh @@ -1,3 +1,4 @@ +#!/bin/sh ./test &> test.txt ./test2 &> test2.txt ./test3 &> test3.txt From 2b9c02e72a06486fb6fb2edbd9d8141fde9ec700 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 13:29:18 -0700 Subject: [PATCH 22/39] use sys.executable --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 6256ae6712147..2bd219a982d9b 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -217,7 +217,7 @@ def new(*args): except: pass config_file = config_file.replace('{{{ NODE }}}', node) - python = 'python' + python = sys.executable or 'python' try: python = Popen(['which', 'python2'], stdout=PIPE).communicate()[0].replace('\n', '') or \ Popen(['which', 'python'], stdout=PIPE).communicate()[0].replace('\n', '') or python From 6c531cbf21e4b332f963b977434dc897e914ca7b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 13:31:53 -0700 Subject: [PATCH 23/39] fix asm.js coercion --- src/library.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library.js b/src/library.js index 3983f52bffd78..dc0dcdd2e19c9 100644 --- a/src/library.js +++ b/src/library.js @@ -4443,7 +4443,7 @@ LibraryManager.library = { pdest = pdest|0; psrc = psrc|0; var i = 0; var pdestEnd = 0; - pdestEnd = (pdest + _strlen(pdest))|0; + pdestEnd = (pdest + (_strlen(pdest)|0))|0; do { {{{ makeCopyValues('pdestEnd+i', 'psrc+i', 1, 'i8', null, 1) }}}; i = (i+1)|0; From 91cf5f4ffc98fb0a610910d19f529ac464d92290 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 14:01:57 -0700 Subject: [PATCH 24/39] assert on no fp80s etc. in non-x86 target --- src/parseTools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parseTools.js b/src/parseTools.js index 2b6218334509d..5cbefdb178206 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -638,6 +638,7 @@ function IEEEUnHex(stringy) { while (stringy.length < 16) stringy = '0' + stringy; if (FAKE_X86_FP80 && stringy.length > 16) { stringy = stringy.substr(stringy.length-16, 16); + assert(TARGET_X86, 'must only see >64 bit floats in x86, as fp80s'); warnOnce('.ll contains floating-point values with more than 64 bits. Faking values for them. If they are used, this will almost certainly break horribly!'); } assert(stringy.length === 16, 'Can only unhex 16-digit double numbers, nothing platform-specific'); // |long double| can cause x86_fp80 which causes this From d8836685674a2cd19b8ba0ac2b112fd189f46bfe Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 4 May 2013 17:30:24 +0200 Subject: [PATCH 25/39] Remove generated file (should not be part of the repository) --- third_party/lzma.js/lzip/config.status | 8 -------- 1 file changed, 8 deletions(-) delete mode 100755 third_party/lzma.js/lzip/config.status diff --git a/third_party/lzma.js/lzip/config.status b/third_party/lzma.js/lzip/config.status deleted file mode 100755 index 610b2a0558790..0000000000000 --- a/third_party/lzma.js/lzip/config.status +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/sh -# This file was generated automatically by configure. Do not edit. -# Run this file to recreate the current configuration. -# -# This script is free software: you have unlimited permission -# to copy, distribute and modify it. - -exec /bin/sh ./configure --no-create From aa7dbbb0bb0cd21c047d0c89638a0804bd60389b Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Sat, 4 May 2013 17:32:14 +0200 Subject: [PATCH 26/39] Remove more +x permissions on source or javascript files --- src/embind/embind.js | 0 src/embind/emval.js | 0 system/include/emscripten/bind.h | 0 system/include/emscripten/wire.h | 0 tests/embind/build_benchmark | 0 tests/embind/embind.test.js | 0 tests/embind/imvu_test_adapter.js | 0 tests/embind/underscore-1.4.2.js | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/embind/embind.js mode change 100755 => 100644 src/embind/emval.js mode change 100755 => 100644 system/include/emscripten/bind.h mode change 100755 => 100644 system/include/emscripten/wire.h mode change 100755 => 100644 tests/embind/build_benchmark mode change 100755 => 100644 tests/embind/embind.test.js mode change 100755 => 100644 tests/embind/imvu_test_adapter.js mode change 100755 => 100644 tests/embind/underscore-1.4.2.js diff --git a/src/embind/embind.js b/src/embind/embind.js old mode 100755 new mode 100644 diff --git a/src/embind/emval.js b/src/embind/emval.js old mode 100755 new mode 100644 diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h old mode 100755 new mode 100644 diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h old mode 100755 new mode 100644 diff --git a/tests/embind/build_benchmark b/tests/embind/build_benchmark old mode 100755 new mode 100644 diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js old mode 100755 new mode 100644 diff --git a/tests/embind/imvu_test_adapter.js b/tests/embind/imvu_test_adapter.js old mode 100755 new mode 100644 diff --git a/tests/embind/underscore-1.4.2.js b/tests/embind/underscore-1.4.2.js old mode 100755 new mode 100644 From 0560adda8a6c0259478a54e5b514ceaafe8fc10c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 4 May 2013 09:49:52 -0700 Subject: [PATCH 27/39] emit aborting stubs for DEAD_FUNCTIONS --- src/jsifier.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsifier.js b/src/jsifier.js index 46d8ae74793ca..c21e7995dc712 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -490,7 +490,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) { if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident); if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) printErr('warning: unresolved symbol: ' + shortident); - if (ASM_JS) { + if (ASM_JS || item.ident in DEAD_FUNCTIONS) { // emit a stub that will fail during runtime. this allows asm validation to succeed. LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); } else { From eadd89b7c87921ea3274e76017046b8bf884b336 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2013 16:40:18 -0700 Subject: [PATCH 28/39] make memory management sane: 0 is null, then static including globals, then stack, then dynamic/sbrk. deprecate shared libs (BUILD_AS_SHARED_LIB) --- src/compiler.js | 6 ++- src/jsifier.js | 43 ++++++++++++++++----- src/library.js | 74 +++++++++++++++++++------------------ src/library_gc.js | 7 +--- src/parseTools.js | 5 +-- src/postamble.js | 6 +-- src/preamble.js | 59 +++++++++-------------------- src/runtime.js | 17 ++++++++- src/settings.js | 3 +- tests/cases/gepoverflow.txt | 2 +- tests/fcntl/output.txt | 2 +- tests/fcntl/src.c | 2 +- tests/runner.py | 10 ++++- 13 files changed, 132 insertions(+), 104 deletions(-) diff --git a/src/compiler.js b/src/compiler.js index 313fd5f7d6073..8b9606f14d993 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -184,6 +184,7 @@ if (ASM_JS) { assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2'); } assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals +assert(!BUILD_AS_SHARED_LIB, 'shared libs are deprecated'); // Output some info and warnings based on settings @@ -208,7 +209,10 @@ load('parseTools.js'); load('intertyper.js'); load('analyzer.js'); load('jsifier.js'); -if (RELOOP) load(RELOOPER) +if (RELOOP) { + load(RELOOPER); + assert(typeof Relooper != 'undefined'); +} globalEval(processMacros(preprocess(read('runtime.js')))); Runtime.QUANTUM_SIZE = QUANTUM_SIZE; diff --git a/src/jsifier.js b/src/jsifier.js index c21e7995dc712..8270b443cadea 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1546,13 +1546,9 @@ function JSify(data, functionsOnly, givenFunctions) { if (!mainPass) { if (phase == 'pre' && !Variables.generatedGlobalBase) { Variables.generatedGlobalBase = true; - if (Variables.nextIndexedOffset > 0) { - // Variables have been calculated, get to base stuff before we print them - // GLOBAL_BASE is statically known to be equal to STACK_MAX and to TOTAL_STACK, assert on this - print('assert(STATICTOP == STACK_MAX); assert(STACK_MAX == TOTAL_STACK);\n'); - print('STATICTOP += ' + Variables.nextIndexedOffset + ';\n'); - print('assert(STATICTOP < TOTAL_MEMORY);\n'); - } + // Globals are done, here is the rest of static memory + print('STATIC_BASE = ' + Runtime.GLOBAL_BASE + ';\n'); + print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); } var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable); print(generated.map(function(item) { return item.JS }).join('\n')); @@ -1573,13 +1569,13 @@ function JSify(data, functionsOnly, givenFunctions) { // possibly function table {{{ FT_* }}} etc. if (value.indexOf('{{ ') < 0) return true; } - writeInt8s(memoryInitialization, target - TOTAL_STACK, value, type); + writeInt8s(memoryInitialization, target - Runtime.GLOBAL_BASE, value, type); return false; } return true; }); // write out the singleton big memory initialization value - print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'TOTAL_STACK', true)); // we assert on TOTAL_STACK == GLOBAL_BASE + print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'Runtime.GLOBAL_BASE', true)); } else { print('/* no memory initializer */'); // test purposes } @@ -1589,6 +1585,27 @@ function JSify(data, functionsOnly, givenFunctions) { print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n')); print('}\n'); print('if (!awaitingMemoryInitializer) runPostSets();\n'); // if we load the memory initializer, this is done later + + if (USE_TYPED_ARRAYS == 2) { + print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n'); + print('assert(tempDoublePtr % 8 == 0);\n'); + print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n'); + print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); + print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); + print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); + print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); + print('}\n'); + print('function copyTempDouble(ptr) {\n'); + print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n'); + print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n'); + print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n'); + print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n'); + print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n'); + print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n'); + print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n'); + print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n'); + print('}\n'); + } } return; @@ -1622,6 +1639,12 @@ function JSify(data, functionsOnly, givenFunctions) { legalizedI64s = legalizedI64sDefault; + print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n'); + print('staticSealed = true; // seal the static portion of memory\n'); + print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n'); + print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n'); + print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n'); + if (asmLibraryFunctions.length > 0) { print('// ASM_LIBRARY FUNCTIONS'); function fix(f) { // fix indenting to not confuse js optimizer @@ -1631,6 +1654,7 @@ function JSify(data, functionsOnly, givenFunctions) { } print(asmLibraryFunctions.map(fix).join('\n')); } + } else { if (singlePhase) { assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss])); @@ -1664,6 +1688,7 @@ function JSify(data, functionsOnly, givenFunctions) { assert(typeof dep == 'function'); var text = dep(); assert(text.indexOf('\n') < 0); + text = text.replace('ALLOC_STATIC', 'ALLOC_DYNAMIC'); print('/* PRE_ASM */ ' + text + '\n'); }); } diff --git a/src/library.js b/src/library.js index dc0dcdd2e19c9..e984b1eb40bc4 100644 --- a/src/library.js +++ b/src/library.js @@ -15,16 +15,18 @@ // object. For convenience, the short name appears here. Note that if you add a // new function with an '_', it will not be found. +// Memory allocated during startup, in postsets, should only be ALLOC_STATIC + LibraryManager.library = { // ========================================================================== // File system base. // ========================================================================== // keep this low in memory, because we flatten arrays with them in them - stdin: 'allocate(1, "i32*", ALLOC_STACK)', - stdout: 'allocate(1, "i32*", ALLOC_STACK)', - stderr: 'allocate(1, "i32*", ALLOC_STACK)', - _impure_ptr: 'allocate(1, "i32*", ALLOC_STACK)', + stdin: 'allocate(1, "i32*", ALLOC_STATIC)', + stdout: 'allocate(1, "i32*", ALLOC_STATIC)', + stderr: 'allocate(1, "i32*", ALLOC_STATIC)', + _impure_ptr: 'allocate(1, "i32*", ALLOC_STATIC)', $FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'], $FS__postset: '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' + @@ -573,7 +575,7 @@ LibraryManager.library = { eof: false, ungotten: [] }; - assert(Math.max(_stdin, _stdout, _stderr) < 1024); // make sure these are low, we flatten arrays with these + // TODO: put these low in memory like we used to assert on: assert(Math.max(_stdin, _stdout, _stderr) < 15000); // make sure these are low, we flatten arrays with these {{{ makeSetValue(makeGlobalUse('_stdin'), 0, 1, 'void*') }}}; {{{ makeSetValue(makeGlobalUse('_stdout'), 0, 2, 'void*') }}}; {{{ makeSetValue(makeGlobalUse('_stderr'), 0, 3, 'void*') }}}; @@ -590,11 +592,11 @@ LibraryManager.library = { FS.streams[_stderr] = FS.streams[3]; #if ASSERTIONS FS.checkStreams(); - assert(FS.streams.length < 1024); // at this early stage, we should not have a large set of file descriptors - just a few + // see previous TODO on stdin etc.: assert(FS.streams.length < 1024); // at this early stage, we should not have a large set of file descriptors - just a few #endif allocate([ allocate( {{{ Runtime.QUANTUM_SIZE === 4 ? '[0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0]' : '[0, _stdin, _stdout, _stderr]' }}}, - 'void*', ALLOC_STATIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}}); + 'void*', ALLOC_DYNAMIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}}); }, quit: function() { @@ -2425,22 +2427,17 @@ LibraryManager.library = { // Implement a Linux-like 'memory area' for our 'process'. // Changes the size of the memory area by |bytes|; returns the // address of the previous top ('break') of the memory area - - // We need to make sure no one else allocates unfreeable memory! - // We must control this entirely. So we don't even need to do - // unfreeable allocations - the HEAP is ours, from STATICTOP up. - // TODO: We could in theory slice off the top of the HEAP when - // sbrk gets a negative increment in |bytes|... + // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP var self = _sbrk; if (!self.called) { - STATICTOP = alignMemoryPage(STATICTOP); // make sure we start out aligned + DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned self.called = true; -#if GC_SUPPORT - _sbrk.DYNAMIC_START = STATICTOP; -#endif + assert(Runtime.dynamicAlloc); + self.alloc = Runtime.dynamicAlloc; + Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') }; } - var ret = STATICTOP; - if (bytes != 0) Runtime.staticAlloc(bytes); + var ret = DYNAMICTOP; + if (bytes != 0) self.alloc(bytes); return ret; // Previous break location. }, open64: 'open', @@ -3007,16 +3004,20 @@ LibraryManager.library = { } case 's': { // String. - var arg = getNextArg('i8*') || nullString; - var argLength = _strlen(arg); + var arg = getNextArg('i8*'); + var argLength = arg ? _strlen(arg) : '(null)'.length; if (precisionSet) argLength = Math.min(argLength, precision); if (!flagLeftAlign) { while (argLength < width--) { ret.push({{{ charCode(' ') }}}); } } - for (var i = 0; i < argLength; i++) { - ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); + if (arg) { + for (var i = 0; i < argLength; i++) { + ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}}); + } + } else { + ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true)); } if (flagLeftAlign) { while (argLength < width--) { @@ -3750,7 +3751,7 @@ LibraryManager.library = { * implementation (replaced by dlmalloc normally) so * not an issue. */ - var ptr = Runtime.staticAlloc(bytes + 8); + var ptr = Runtime.dynamicAlloc(bytes + 8); return (ptr+8) & 0xFFFFFFF8; }, free: function(){}, @@ -4029,7 +4030,7 @@ LibraryManager.library = { _free(temp); }, - environ: 'allocate(1, "i32*", ALLOC_STACK)', + environ: 'allocate(1, "i32*", ALLOC_STATIC)', __environ__deps: ['environ'], __environ: '_environ', __buildEnvironment__deps: ['__environ'], @@ -4925,7 +4926,7 @@ LibraryManager.library = { } return 8; } - return 'var ctlz_i8 = allocate([' + range(256).map(function(x) { return ctlz(x) }).join(',') + '], "i8", ALLOC_STACK);'; + return 'var ctlz_i8 = allocate([' + range(256).map(function(x) { return ctlz(x) }).join(',') + '], "i8", ALLOC_STATIC);'; }], llvm_ctlz_i32__asm: true, llvm_ctlz_i32__sig: 'ii', @@ -4961,7 +4962,7 @@ LibraryManager.library = { } return 8; } - return 'var cttz_i8 = allocate([' + range(256).map(function(x) { return cttz(x) }).join(',') + '], "i8", ALLOC_STACK);'; + return 'var cttz_i8 = allocate([' + range(256).map(function(x) { return cttz(x) }).join(',') + '], "i8", ALLOC_STATIC);'; }], llvm_cttz_i32__asm: true, llvm_cttz_i32__sig: 'ii', @@ -5919,11 +5920,11 @@ LibraryManager.library = { ['i32', 'tm_gmtoff'], ['i32', 'tm_zone']]), // Statically allocated time struct. - __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STACK)', + __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', // Statically allocated timezone strings. __tm_timezones: {}, // Statically allocated time strings. - __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STACK)', + __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', mktime__deps: ['__tm_struct_layout', 'tzset'], mktime: function(tmPtr) { @@ -6057,9 +6058,9 @@ LibraryManager.library = { // TODO: Initialize these to defaults on startup from system settings. // Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm) - _tzname: 'allocate({{{ 2*Runtime.QUANTUM_SIZE }}}, "i32*", ALLOC_STACK)', - _daylight: 'allocate(1, "i32*", ALLOC_STACK)', - _timezone: 'allocate(1, "i32*", ALLOC_STACK)', + _tzname: 'allocate({{{ 2*Runtime.QUANTUM_SIZE }}}, "i32*", ALLOC_STATIC)', + _daylight: 'allocate(1, "i32*", ALLOC_STATIC)', + _timezone: 'allocate(1, "i32*", ALLOC_STATIC)', tzset__deps: ['_tzname', '_daylight', '_timezone'], tzset: function() { // TODO: Use (malleable) environment variables instead of system settings. @@ -6756,15 +6757,18 @@ LibraryManager.library = { 26: 'Text file busy', 18: 'Invalid cross-device link' }, - __setErrNo__postset: '___setErrNo(0);', __setErrNo: function(value) { // For convenient setting and returning of errno. - if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_STATIC); + if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL); {{{ makeSetValue('___setErrNo.ret', '0', 'value', 'i32') }}} return value; }, __errno_location__deps: ['__setErrNo'], __errno_location: function() { + if (!___setErrNo.ret) { + ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL); + {{{ makeSetValue('___setErrNo.ret', '0', '0', 'i32') }}} + } return ___setErrNo.ret; }, __errno: '__errno_location', @@ -6877,7 +6881,7 @@ LibraryManager.library = { void **restrict stackaddr, size_t *restrict stacksize); */ /*FIXME: assumes that there is only one thread, and that attr is the current thread*/ - {{{ makeSetValue('stackaddr', '0', 'STACK_ROOT', 'i8*') }}} + {{{ makeSetValue('stackaddr', '0', 'STACK_BASE', 'i8*') }}} {{{ makeSetValue('stacksize', '0', 'TOTAL_STACK', 'i32') }}} return 0; }, diff --git a/src/library_gc.js b/src/library_gc.js index f6db74d86fc8d..2a1642508ea46 100644 --- a/src/library_gc.js +++ b/src/library_gc.js @@ -148,12 +148,9 @@ if (GC_SUPPORT) { prep: function() { // Clear reachables and scan for roots GC.reachable = {}; // 1 if reachable. XXX GC.reachableList = []; // each reachable is added once to this. XXX - // static data areas - var staticStart = STACK_MAX; - var staticEnd = _sbrk.DYNAMIC_START || STATICTOP; // after DYNAMIC_START, sbrk manages it (but it might not exist yet) - GC.scan(staticStart, staticEnd); + GC.scan(STATIC_BASE, STATICTOP); // TODO: scan stack and registers. Currently we assume we run from a timeout or such, so no stack/regs - // stack: STACK_ROOT to STACKTOP + // stack: STACK_BASE to STACKTOP // registers: call scanners }, diff --git a/src/parseTools.js b/src/parseTools.js index 5cbefdb178206..db834206fca1c 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -465,8 +465,7 @@ function makeGlobalUse(ident) { UNINDEXABLE_GLOBALS[ident] = 1; return ident; } - // We know and assert on TOTAL_STACK being equal to GLOBAL_BASE - return (TOTAL_STACK + index).toString(); + return (Runtime.GLOBAL_BASE + index).toString(); } return ident; } @@ -1594,7 +1593,7 @@ function makePointer(slab, pos, allocator, type, ptr, finalMemoryInitialization) // writing out into memory, without a normal allocation. We put all of these into a single big chunk. assert(typeof slab == 'object'); assert(slab.length % QUANTUM_SIZE == 0, slab.length); // must be aligned already - var offset = ptr - TOTAL_STACK; // we assert on GLOBAL_BASE being equal to TOTAL_STACK + var offset = ptr - Runtime.GLOBAL_BASE; for (var i = 0; i < slab.length; i++) { memoryInitialization[offset + i] = slab[i]; } diff --git a/src/postamble.js b/src/postamble.js index 8dd0158905b40..12471a196ec26 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -15,14 +15,14 @@ Module.callMain = function callMain(args) { argv.push(0); } } - var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC) ]; + var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ]; pad(); for (var i = 0; i < argc-1; i = i + 1) { - argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_STATIC)); + argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL)); pad(); } argv.push(0); - argv = allocate(argv, 'i32', ALLOC_STATIC); + argv = allocate(argv, 'i32', ALLOC_NORMAL); #if BENCHMARK var start = Date.now(); diff --git a/src/preamble.js b/src/preamble.js index cac0be4c245ca..d10771e36d421 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -38,14 +38,14 @@ var ACCEPTABLE_SAFE_HEAP_ERRORS = 0; function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) { //if (dest === A_NUMBER) Module.print ([dest, type, store, ignore, storeValue] + ' ' + new Error().stack); // Something like this may be useful, in debugging - assert(dest >= STACK_ROOT, 'segmentation fault: null pointer, or below normal memory'); + assert(dest > 0, 'segmentation fault'); #if USE_TYPED_ARRAYS // When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must // correct that by growing TOTAL_MEMORY as needed. Without typed arrays, memory is a normal // JS array so it will work (potentially slowly, depending on the engine). - assert(ignore || dest < STATICTOP); - assert(ignore || STATICTOP <= TOTAL_MEMORY); + assert(ignore || dest < Math.max(DYNAMICTOP, STATICTOP)); + assert(ignore || DYNAMICTOP <= TOTAL_MEMORY); #endif #if USE_TYPED_ARRAYS == 2 @@ -417,10 +417,12 @@ Module['getValue'] = getValue; var ALLOC_NORMAL = 0; // Tries to use _malloc() var ALLOC_STACK = 1; // Lives for the duration of the current function call var ALLOC_STATIC = 2; // Cannot be freed -var ALLOC_NONE = 3; // Do not allocate +var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk +var ALLOC_NONE = 4; // Do not allocate Module['ALLOC_NORMAL'] = ALLOC_NORMAL; Module['ALLOC_STACK'] = ALLOC_STACK; Module['ALLOC_STATIC'] = ALLOC_STATIC; +Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC; Module['ALLOC_NONE'] = ALLOC_NONE; // allocate(): This is for internal use. You can use it yourself as well, but the interface @@ -452,7 +454,7 @@ function allocate(slab, types, allocator, ptr) { if (allocator == ALLOC_NONE) { ret = ptr; } else { - ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); + ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); } if (zeroinit) { @@ -573,8 +575,10 @@ var FHEAP; var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; #endif -var STACK_ROOT, STACKTOP, STACK_MAX; -var STATICTOP; +var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area +var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area +var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk + #if USE_TYPED_ARRAYS function enlargeMemory() { #if ALLOW_MEMORY_GROWTH == 0 @@ -584,13 +588,13 @@ function enlargeMemory() { abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.'); #endif #else - // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top. + // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top. #if ASSERTIONS - Module.printErr('Warning: Enlarging memory arrays, this is not fast, and ALLOW_MEMORY_GROWTH is not fully tested with all optimizations on! ' + [STATICTOP, TOTAL_MEMORY]); // We perform safe elimination instead of elimination in this mode, but if you see this error, try to disable it and other optimizations entirely - assert(STATICTOP >= TOTAL_MEMORY); + Module.printErr('Warning: Enlarging memory arrays, this is not fast, and ALLOW_MEMORY_GROWTH is not fully tested with all optimizations on! ' + [DYNAMICTOP, TOTAL_MEMORY]); // We perform safe elimination instead of elimination in this mode, but if you see this error, try to disable it and other optimizations entirely + assert(DYNAMICTOP >= TOTAL_MEMORY); assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite #endif - while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it + while (TOTAL_MEMORY <= DYNAMICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY); } assert(TOTAL_MEMORY <= Math.pow(2, 30)); // 2^30==1GB is a practical maximum - 2^31 is already close to possible negative numbers etc. @@ -680,35 +684,6 @@ Module['HEAPF32'] = HEAPF32; Module['HEAPF64'] = HEAPF64; #endif -STACK_ROOT = STACKTOP = Runtime.alignMemory(1); -STACK_MAX = TOTAL_STACK; // we lose a little stack here, but TOTAL_STACK is nice and round so use that as the max - -#if USE_TYPED_ARRAYS == 2 -var tempDoublePtr = Runtime.alignMemory(allocate(12, 'i8', ALLOC_STACK), 8); -assert(tempDoublePtr % 8 == 0); -function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; -} -function copyTempDouble(ptr) { - HEAP8[tempDoublePtr] = HEAP8[ptr]; - HEAP8[tempDoublePtr+1] = HEAP8[ptr+1]; - HEAP8[tempDoublePtr+2] = HEAP8[ptr+2]; - HEAP8[tempDoublePtr+3] = HEAP8[ptr+3]; - HEAP8[tempDoublePtr+4] = HEAP8[ptr+4]; - HEAP8[tempDoublePtr+5] = HEAP8[ptr+5]; - HEAP8[tempDoublePtr+6] = HEAP8[ptr+6]; - HEAP8[tempDoublePtr+7] = HEAP8[ptr+7]; -} -#endif - -STATICTOP = STACK_MAX; -assert(STATICTOP < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY - -var nullString = allocate(intArrayFromString('(null)'), 'i8', ALLOC_STACK); - function callRuntimeCallbacks(callbacks) { while(callbacks.length > 0) { var callback = callbacks.shift(); @@ -907,9 +882,9 @@ var awaitingMemoryInitializer = false; function loadMemoryInitializer(filename) { function applyData(data) { #if USE_TYPED_ARRAYS == 2 - HEAPU8.set(data, TOTAL_STACK); + HEAPU8.set(data, STATIC_BASE); #else - allocate(data, 'i8', ALLOC_NONE, TOTAL_STACK); + allocate(data, 'i8', ALLOC_NONE, STATIC_BASE); #endif runPostSets(); } diff --git a/src/runtime.js b/src/runtime.js index 9daab820a2c66..9bedfe68aa757 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -61,8 +61,16 @@ var RuntimeGenerator = { // An allocation that cannot normally be free'd (except through sbrk, which once // called, takes control of STATICTOP) staticAlloc: function(size) { + if (ASSERTIONS) size = '(assert(!staticSealed),' + size + ')'; // static area must not be sealed var ret = RuntimeGenerator.alloc(size, 'STATIC', INIT_HEAP); - if (USE_TYPED_ARRAYS) ret += '; if (STATICTOP >= TOTAL_MEMORY) enlargeMemory();' + return ret; + }, + + // allocation on the top of memory, adjusted dynamically by sbrk + dynamicAlloc: function(size) { + if (ASSERTIONS) size = '(assert(DYNAMICTOP > 0),' + size + ')'; // dynamic area must be ready + var ret = RuntimeGenerator.alloc(size, 'DYNAMIC', INIT_HEAP); + if (USE_TYPED_ARRAYS) ret += '; if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();' return ret; }, @@ -466,6 +474,7 @@ var Runtime = { Runtime.stackAlloc = unInline('stackAlloc', ['size']); Runtime.staticAlloc = unInline('staticAlloc', ['size']); +Runtime.dynamicAlloc = unInline('dynamicAlloc', ['size']); Runtime.alignMemory = unInline('alignMemory', ['size', 'quantum']); Runtime.makeBigInt = unInline('makeBigInt', ['low', 'high', 'unsigned']); @@ -529,3 +538,9 @@ function reSign(value, bits, ignore, sig) { return value; } +// The address globals begin at. Very low in memory, for code size and optimization opportunities. +// Above 0 is static memory, starting with globals. +// Then the stack. +// Then 'dynamic' memory for sbrk. +Runtime.GLOBAL_BASE = Runtime.alignMemory(1); + diff --git a/src/settings.js b/src/settings.js index 2e4c2550c65b7..ba1f6a834984e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -279,7 +279,8 @@ var PRINT_SPLIT_FILE_MARKER = 0; // Prints markers in Javascript generation to s var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library // 0 here means this is not a shared lib: It is a main file. - // 1 means this is a normal shared lib, load it with dlopen(). + // All shared library options (1 and 2) are currently deprecated XXX + // 1 means this is a normal shared lib, load it with dlopen() // 2 means this is a shared lib that will be linked at runtime, // which means it will insert its functions into // the global namespace. See STATIC_LIBS_TO_LOAD. diff --git a/tests/cases/gepoverflow.txt b/tests/cases/gepoverflow.txt index 31d67161fb825..3984fc07461a9 100644 --- a/tests/cases/gepoverflow.txt +++ b/tests/cases/gepoverflow.txt @@ -1,2 +1,2 @@ -*5242366,5242936* +*-506,64* *-514,56* diff --git a/tests/fcntl/output.txt b/tests/fcntl/output.txt index 1ed740e7297f3..bad9708e03ca5 100644 --- a/tests/fcntl/output.txt +++ b/tests/fcntl/output.txt @@ -1,4 +1,4 @@ -F_DUPFD: 100 +F_DUPFD: 1 errno: 0 F_DUPFD/error1: -1 diff --git a/tests/fcntl/src.c b/tests/fcntl/src.c index c8c71c8a184fd..c60e578e798af 100644 --- a/tests/fcntl/src.c +++ b/tests/fcntl/src.c @@ -5,7 +5,7 @@ int main() { int f = open("/test", O_RDWR, 0777); - printf("F_DUPFD: %d\n", fcntl(f, F_DUPFD, 100)); + printf("F_DUPFD: %d\n", fcntl(f, F_DUPFD, 100) >= 100); printf("errno: %d\n", errno); printf("\n"); errno = 0; diff --git a/tests/runner.py b/tests/runner.py index 0aefb8e131f75..3230fa23e7d0e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -3134,7 +3134,7 @@ def test_segfault(self): Settings.SAFE_HEAP = 1 - for addr in ['0', '7', 'new D2()']: + for addr in ['0', 'new D2()']: print addr src = r''' #include @@ -5018,6 +5018,7 @@ def test_nestedstructs(self): self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*') def test_runtimelink(self): + return self.skip('shared libs are deprecated') if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize printf into puts in the parent, and the child will still look for puts') if Settings.ASM_JS: return self.skip('asm does not support runtime linking') @@ -5036,6 +5037,7 @@ def test_runtimelink(self): self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.') def test_dlfcn_basic(self): + return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.NAMED_GLOBALS = 1 @@ -5090,6 +5092,7 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_qsort(self): + return self.skip('shared libs are deprecated') if self.emcc_args is None: return self.skip('requires emcc') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') @@ -5186,6 +5189,7 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_data_and_fptr(self): + return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func') @@ -5290,6 +5294,7 @@ def process(filename): post_build=add_pre_run_and_checks) def test_dlfcn_alias(self): + return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.LINKABLE = 1 @@ -5347,6 +5352,7 @@ def process(filename): Settings.INCLUDE_FULL_LIBRARY = 0 def test_dlfcn_varargs(self): + return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('TODO: dlopen in asm') Settings.LINKABLE = 1 @@ -9959,6 +9965,7 @@ def test_local_link(self): self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) def test_runtimelink_multi(self): + return self.skip('shared libs are deprecated') if Settings.ASM_JS: return self.skip('asm does not support runtime linking yet') if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey due to node limitations') @@ -12155,6 +12162,7 @@ def test_perspective(self): self.btest('perspective.c', reference='perspective.png') def test_runtimelink(self): + return self.skip('shared libs are deprecated') main, supp = self.setup_runtimelink_test() open(self.in_dir('supp.cpp'), 'w').write(supp) From 9e05d4f86af33dd3e940b9958e2d44d6c7426b02 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 5 May 2013 10:04:59 -0700 Subject: [PATCH 29/39] update test_statics --- tests/runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 3230fa23e7d0e..3dd42c852adeb 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4527,10 +4527,10 @@ def test_trickystring(self): self.do_run(src, 'ok\n') def test_statics(self): - # static initializers save i16 but load i8 for some reason + # static initializers save i16 but load i8 for some reason (or i64 and load i8) if Settings.SAFE_HEAP: Settings.SAFE_HEAP = 3 - Settings.SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26'] + Settings.SAFE_HEAP_LINES = ['src.cpp:19', 'src.cpp:26', 'src.cpp:28'] src = ''' #include From 558ac1930bf2fb014e8906408a5821c61729382a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 5 May 2013 13:20:30 -0700 Subject: [PATCH 30/39] generalize customizeVTable to support asm --- tests/runner.py | 6 ++++-- tools/bindings_generator.py | 21 +++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 3dd42c852adeb..7005718cd9057 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8637,7 +8637,7 @@ def process(filename): Module.Child2.prototype.runVirtualFunc(c2); c2.virtualFunc2(); -''' + ('' if Settings.ASM_JS else ''' +''' + (''' // extend the class from JS var c3 = new Module.Child2; Module.customizeVTable(c3, [{ @@ -8667,6 +8667,8 @@ def process(filename): src.close() ''' + Settings.RESERVED_FUNCTION_POINTERS = 20 + self.do_run(src, '''* 84 c1 @@ -8697,7 +8699,7 @@ def process(filename): *static* *virtualf* *virtualf* -*virtualf2*''' + ('' if Settings.ASM_JS else ''' +*virtualf2*''' + (''' Parent:9 Child2:9 *js virtualf replacement* diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py index d610ab546340e..5bf0996ed9449 100755 --- a/tools/bindings_generator.py +++ b/tools/bindings_generator.py @@ -468,7 +468,6 @@ def explore(subclass, template_name=None, template_value=None): function customizeVTable(object, replacementPairs) { // Does not handle multiple inheritance - // Does not work with asm.js // Find out vtable size var vTable = getValue(object.ptr, 'void*'); @@ -478,23 +477,22 @@ def explore(subclass, template_name=None, template_value=None): size++; } - // Prepare replacement lookup table and add replacements to FUNCTION_TABLE + // Prepare replacement lookup table and add replacements. // There is actually no good way to do this! So we do the following hack: // We create a fake vtable with canary functions, to detect which actual // function is being called var vTable2 = _malloc(size*Runtime.QUANTUM_SIZE); setValue(object.ptr, vTable2, 'void*'); var canaryValue; - var functions = FUNCTION_TABLE.length; + var tempFuncs = []; for (var i = 0; i < size; i++) { - var index = FUNCTION_TABLE.length; (function(j) { - FUNCTION_TABLE.push(function() { + var index = Runtime.addFunction(function() { canaryValue = j; }); + setValue(vTable2 + Runtime.QUANTUM_SIZE*i, index, 'void*'); + tempFuncs.push(index); })(i); - FUNCTION_TABLE.push(0); - setValue(vTable2 + Runtime.QUANTUM_SIZE*i, index, 'void*'); } var args = [{ptr: 0}]; replacementPairs.forEach(function(pair) { @@ -509,16 +507,15 @@ def explore(subclass, template_name=None, template_value=None): } pair.originalIndex = getValue(vTable + canaryValue*Runtime.QUANTUM_SIZE, 'void*'); }); - FUNCTION_TABLE = FUNCTION_TABLE.slice(0, functions); + for (var i = 0; i < size; i++) { + Runtime.removeFunction(tempFuncs[i]); + } // Do the replacements var replacements = {}; replacementPairs.forEach(function(pair) { - var replacementIndex = FUNCTION_TABLE.length; - FUNCTION_TABLE.push(pair['replacement']); - FUNCTION_TABLE.push(0); - replacements[pair.originalIndex] = replacementIndex; + replacements[pair.originalIndex] = Runtime.addFunction(pair['replacement']); }); // Copy and modify vtable From bf673b03ca52e3613b78ddf412cb99be71a4d816 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 5 May 2013 16:12:43 -0700 Subject: [PATCH 31/39] add test for sdl allocation, and warn when using stub malloc/free --- src/library.js | 9 ++++++++- tests/runner.py | 3 +++ tests/sdl_alloctext.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/sdl_alloctext.c diff --git a/src/library.js b/src/library.js index e984b1eb40bc4..cfe83c6e1b896 100644 --- a/src/library.js +++ b/src/library.js @@ -3751,10 +3751,17 @@ LibraryManager.library = { * implementation (replaced by dlmalloc normally) so * not an issue. */ +#if ASSERTIONS + Runtime.warnOnce('using stub malloc (reference it from C to have the real one included)'); +#endif var ptr = Runtime.dynamicAlloc(bytes + 8); return (ptr+8) & 0xFFFFFFF8; }, - free: function(){}, + free: function() { +#if ASSERTIONS + Runtime.warnOnce('using stub free (reference it from C to have the real one included)'); +#endif +}, calloc__deps: ['malloc'], calloc: function(n, s) { diff --git a/tests/runner.py b/tests/runner.py index 7005718cd9057..0d8878c3c252a 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12117,6 +12117,9 @@ def test_sdl_canvas_palette_2(self): self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_g.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-g.js']) self.btest('sdl_canvas_palette_2.c', reference='sdl_canvas_palette_b.png', args=['--pre-js', 'pre.js', '--pre-js', 'args-b.js']) + def test_sdl_alloctext(self): + self.btest('sdl_alloctext.c', expected='1', args=['-O2', '-s', 'TOTAL_MEMORY=' + str(1024*1024*8)]) + def test_glbegin_points(self): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('glbegin_points.c', reference='glbegin_points.png', args=['--preload-file', 'screenshot.png']) diff --git a/tests/sdl_alloctext.c b/tests/sdl_alloctext.c new file mode 100644 index 0000000000000..0ee75f0780f30 --- /dev/null +++ b/tests/sdl_alloctext.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int result = 0; + + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_HWSURFACE); + + TTF_Font *font = TTF_OpenFont("myfont.ttf", 40); + + if (argc == 12) font = (TTF_Font*)malloc(1024); + if (argc % 3) free(font); + + int i = 0; + while (i < 200) + { + printf("%i\n", i); + i++; + + SDL_Color color = { 0xff, 0x99, 0x00, 0xff }; + SDL_Surface *text = TTF_RenderText_Solid(font, "hello world", color); + SDL_BlitSurface (text, NULL, screen, NULL); + + SDL_FreeSurface(text); + } + +#if __EMSCRIPTEN__ + result = 1; + REPORT_RESULT(); +#endif +} + From 2a85aa178d7b14ff689c061361bf50ab85d2573a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 5 May 2013 16:26:22 -0700 Subject: [PATCH 32/39] update comments --- emcc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/emcc b/emcc index 584b7bca33600..9d437ecd5e251 100755 --- a/emcc +++ b/emcc @@ -1131,8 +1131,6 @@ try: not shared.Settings.BUILD_AS_SHARED_LIB == 2: # shared lib 2 use the library in the parent # Check if we need to include some libraries that we compile. (We implement libc ourselves in js, but # compile a malloc implementation and stdlibc++.) - # Note that we assume a single symbol is enough to know if we have/do not have dlmalloc etc. If you - # include just a few symbols but want the rest, this will not work. def read_symbols(path, exclude=None): symbols = map(lambda line: line.strip().split(' ')[1], open(path).readlines()) @@ -1328,9 +1326,10 @@ try: #logging.info('using libcxxabi, this may need CORRECT_* options') #shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1 - # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky # Settings this in the environment will avoid checking dependencies and make building big projects a little faster force = os.environ.get('EMCC_FORCE_STDLIBS') + + # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky. has = need = None for name, create, fix, library_symbols in [('libcxx', create_libcxx, fix_libcxx, libcxx_symbols), ('libcextra', create_libcextra, fix_libcextra, libcextra_symbols), From fc41fce2f5e9ac88939bb55d3391fbedbaafbf6a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 5 May 2013 18:05:44 -0700 Subject: [PATCH 33/39] generate empty function tables of proper size --- emscripten.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emscripten.py b/emscripten.py index 924012af6bdf8..7352b293c18db 100755 --- a/emscripten.py +++ b/emscripten.py @@ -371,7 +371,7 @@ class Counter: sig = use[8:len(use)-4] if sig not in last_forwarded_json['Functions']['tables']: if DEBUG: print >> sys.stderr, 'add empty function table', sig - last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [0,0];\n' + last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [' + ','.join(['0']*forwarded_json['Functions']['nextIndex']) + '];\n' def make_table(sig, raw): i = Counter.i From b6b9c54b99596dbe4471ebe21a171ef869afaa8e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2013 11:38:26 -0700 Subject: [PATCH 34/39] fix memory initializer detection --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index 9d437ecd5e251..cd6e34aef0100 100755 --- a/emcc +++ b/emcc @@ -1570,7 +1570,7 @@ try: if os.path.abspath(memfile) != os.path.abspath(memfile): shutil.copyfile(memfile, temp_memfile) return 'loadMemoryInitializer("%s");' % os.path.basename(memfile) - src = re.sub('/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, TOTAL_STACK\)', repl, src, count=1) + src = re.sub('/\* memory initializer \*/ allocate\(([\d,\.concat\(\)\[\]\\n ]+)"i8", ALLOC_NONE, Runtime\.GLOBAL_BASE\)', repl, src, count=1) open(final + '.mem.js', 'w').write(src) final += '.mem.js' if DEBUG: From 300e44e4239d8d1d8a1684582fd4638d734fa631 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2013 12:04:29 -0700 Subject: [PATCH 35/39] remove tests/cases/gepoverflow since it is too finicky with absolute pointers --- tests/cases/gepoverflow.ll | 37 ---------------------------------- tests/cases/gepoverflow.txt | 2 -- tests/cases/gepoverflow_q1.txt | 1 - 3 files changed, 40 deletions(-) delete mode 100644 tests/cases/gepoverflow.ll delete mode 100644 tests/cases/gepoverflow.txt delete mode 100644 tests/cases/gepoverflow_q1.txt diff --git a/tests/cases/gepoverflow.ll b/tests/cases/gepoverflow.ll deleted file mode 100644 index d09afd8799f9e..0000000000000 --- a/tests/cases/gepoverflow.ll +++ /dev/null @@ -1,37 +0,0 @@ -; ModuleID = 'src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" -target triple = "i386-pc-linux-gnu" - -; XXX Note: the .txt file contains raw pointer data! The important thing is that the two pointers -; on the first line are of the same scale. If one is huge and the other not, then we failed. -; That is an overflow, which overflow checks should catch. -; If we change memory stuff - like the default stack! - we will need to change this. - -@.str2 = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=0] -@.str = private constant [9 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1] -@base = internal constant [31 x i16] [i16 3, i16 4, i16 5, i16 6, i16 7, i16 8, i16 9, i16 10, i16 11, i16 13, i16 15, i16 17, i16 19, i16 23, i16 27, i16 31, i16 35, i16 43, i16 51, i16 59, i16 67, i16 83, i16 99, i16 115, i16 131, i16 163, i16 195, i16 227, i16 258, i16 0, i16 0], align 32 ; [#uses=2] - -; [#uses=2] -declare i32 @printf(i8* noalias, ...) nounwind - -; [#uses=0] -define i32 @main() { -entry: - %retval = alloca i32 ; [#uses=1] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - %baseint = ptrtoint [31 x i16]* @base to i32 ; [#uses=1] - %0 = getelementptr [31 x i16]* @base, i32 69273657, i32 24 ; [#uses=1] - %1 = ptrtoint i16* %0 to i32 ; [#uses=2] - %2 = add i32 %1, 570 ; [#uses=2] - %3 = sub i32 %1, %baseint ; [#uses=1] - %4 = sub i32 %2, %baseint ; [#uses=1] - %5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i32 %1, i32 %2) ; [#uses=0] - %6 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str, i32 0, i32 0), i32 %3, i32 %4) ; [#uses=0] - br label %return - -return: ; preds = %entry - store i32 0, i32* %retval - %retval1 = load i32* %retval ; [#uses=1] - ret i32 %retval1 -} - diff --git a/tests/cases/gepoverflow.txt b/tests/cases/gepoverflow.txt deleted file mode 100644 index 3984fc07461a9..0000000000000 --- a/tests/cases/gepoverflow.txt +++ /dev/null @@ -1,2 +0,0 @@ -*-506,64* -*-514,56* diff --git a/tests/cases/gepoverflow_q1.txt b/tests/cases/gepoverflow_q1.txt deleted file mode 100644 index e32e76dd5f0ec..0000000000000 --- a/tests/cases/gepoverflow_q1.txt +++ /dev/null @@ -1 +0,0 @@ -skip From 1086b716159e25b8ba480052d651d41e2f5f05cc Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2013 12:21:27 -0700 Subject: [PATCH 36/39] make sure function table size for empty tables is the right power of two --- emscripten.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/emscripten.py b/emscripten.py index 7352b293c18db..35edc515cf4cc 100755 --- a/emscripten.py +++ b/emscripten.py @@ -309,6 +309,11 @@ def load_from_cache(chunk): forwarded_json['Functions']['indexedFunctions'][indexed] = i # make sure not to modify this python object later - we use it in indexize i += 2 forwarded_json['Functions']['nextIndex'] = i + function_table_size = forwarded_json['Functions']['nextIndex'] + i = 1 + while i < function_table_size: + i *= 2 + function_table_size = i def split_32(x): x = int(x) @@ -371,7 +376,7 @@ class Counter: sig = use[8:len(use)-4] if sig not in last_forwarded_json['Functions']['tables']: if DEBUG: print >> sys.stderr, 'add empty function table', sig - last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [' + ','.join(['0']*forwarded_json['Functions']['nextIndex']) + '];\n' + last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [' + ','.join(['0']*function_table_size) + '];\n' def make_table(sig, raw): i = Counter.i From be0fb5cc46392c203c5c7885efdfe4f0cd579751 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2013 13:24:39 -0700 Subject: [PATCH 37/39] auto-include malloc/free when SDL is used; fixes #1139 --- emcc | 46 ++++++++++++++++++++++++++++-------------- system/lib/sdl.cpp | 13 ++++++++++++ system/lib/sdl.symbols | 1 + tests/sdl_alloctext.c | 6 +----- 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 system/lib/sdl.cpp create mode 100644 system/lib/sdl.symbols diff --git a/emcc b/emcc index cd6e34aef0100..30cc6873e7ddf 100755 --- a/emcc +++ b/emcc @@ -1141,6 +1141,7 @@ try: # XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not # a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible. libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols')) + sdl_symbols = read_symbols(shared.path_from_root('system', 'lib', 'sdl.symbols')) libcextra_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcextra.symbols')) libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols) libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols) @@ -1187,7 +1188,7 @@ try: ]; return build_libc('libc.bc', libc_files) - def fix_libc(need): + def apply_libc(need): # libc needs some sign correction. # If we are in mode 0, switch to 2. We will add our lines try: if shared.Settings.CORRECT_SIGNS == 0: raise Exception('we need to change to 2') @@ -1197,6 +1198,7 @@ try: shared.Settings.CORRECT_SIGNS_LINES = [shared.path_from_root('src', 'dlmalloc.c') + ':' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]] # If we are in mode 1, we are correcting everything anyhow. If we are in mode 3, we will be corrected # so all is well anyhow too. + return True # libcextra def create_libcextra(): @@ -1274,9 +1276,6 @@ try: libcextra_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources] return build_libc('libcextra.bc', libcextra_files) - def fix_libcextra(need): - pass - # libcxx def create_libcxx(): logging.debug('building libcxx for cache') @@ -1306,11 +1305,12 @@ try: ] return build_libcxx(os.path.join('system', 'lib', 'libcxx'), 'libcxx.bc', libcxx_files) - def fix_libcxx(need): + def apply_libcxx(need): assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1' # libcxx might need corrections, so turn them all on. TODO: check which are actually needed shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1 #logging.info('using libcxx turns on CORRECT_* options') + return True # libcxxabi - just for dynamic_cast for now def create_libcxxabi(): @@ -1321,25 +1321,43 @@ try: ] return build_libcxx(os.path.join('system', 'lib', 'libcxxabi', 'src'), 'libcxxabi.bc', libcxxabi_files) - def fix_libcxxabi(need): + def apply_libcxxabi(need): assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1' #logging.info('using libcxxabi, this may need CORRECT_* options') #shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1 + return True + + # SDL. We include code that demands malloc/free if not already required, so we have proper malloc/free from JS SDL code. + # Note that the Force instance here can be optimized out, but we still export malloc/free, so they will be kept alive. + def create_sdl(): + return build_libcxx(os.path.join('system', 'lib'), 'sdl.bc', ['sdl.cpp']) + + def apply_sdl(need): + return 'malloc' not in all_needed or 'free' not in all_needed # Settings this in the environment will avoid checking dependencies and make building big projects a little faster force = os.environ.get('EMCC_FORCE_STDLIBS') + # Scan symbols + all_needed = set() + symbolses = map(lambda temp_file: shared.Building.llvm_nm(temp_file), temp_files) + for symbols in symbolses: + all_needed.update(symbols.undefs) + for symbols in symbolses: + all_needed.difference_update(symbols.defs) + + # Go over libraries to figure out which we must include # If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky. has = need = None - for name, create, fix, library_symbols in [('libcxx', create_libcxx, fix_libcxx, libcxx_symbols), - ('libcextra', create_libcextra, fix_libcextra, libcextra_symbols), - ('libcxxabi', create_libcxxabi, fix_libcxxabi, libcxxabi_symbols), - ('libc', create_libc, fix_libc, libc_symbols)]: + for name, create, apply_, library_symbols in [('libcxx', create_libcxx, apply_libcxx, libcxx_symbols), + ('libcextra', create_libcextra, lambda x: True, libcextra_symbols), + ('libcxxabi', create_libcxxabi, apply_libcxxabi, libcxxabi_symbols), + ('sdl', create_sdl, apply_sdl, sdl_symbols), + ('libc', create_libc, apply_libc, libc_symbols)]: if not force: need = set() has = set() - for temp_file in temp_files: - symbols = shared.Building.llvm_nm(temp_file) + for symbols in symbolses: for library_symbol in library_symbols: if library_symbol in symbols.undefs: need.add(library_symbol) @@ -1349,14 +1367,12 @@ try: if haz in need: need.remove(haz) logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has))) - if force or len(need) > 0: + if (force or len(need) > 0) and apply_(need): # We need to build and link the library in logging.debug('including %s' % name) libfile = shared.Cache.get(name, create) extra_files_to_link.append(libfile) force = True - if fix and need: - fix(need) # First, combine the bitcode files if there are several. We must also link if we have a singleton .a if len(input_files) + len(extra_files_to_link) > 1 or \ diff --git a/system/lib/sdl.cpp b/system/lib/sdl.cpp new file mode 100644 index 0000000000000..7038cdb147656 --- /dev/null +++ b/system/lib/sdl.cpp @@ -0,0 +1,13 @@ + +#include + +// force malloc&free to be included in from libc +struct Force { + Force() { + void *x = malloc(10); + free(x); + } +}; + +static Force f; + diff --git a/system/lib/sdl.symbols b/system/lib/sdl.symbols new file mode 100644 index 0000000000000..c2c0af4272ffe --- /dev/null +++ b/system/lib/sdl.symbols @@ -0,0 +1 @@ + W SDL_Init diff --git a/tests/sdl_alloctext.c b/tests/sdl_alloctext.c index 0ee75f0780f30..3def2b285c8be 100644 --- a/tests/sdl_alloctext.c +++ b/tests/sdl_alloctext.c @@ -1,9 +1,8 @@ #include -#include #include #include -int main(int argc, char **argv) +int main() { int result = 0; @@ -12,9 +11,6 @@ int main(int argc, char **argv) TTF_Font *font = TTF_OpenFont("myfont.ttf", 40); - if (argc == 12) font = (TTF_Font*)malloc(1024); - if (argc % 3) free(font); - int i = 0; while (i < 200) { From b08947097b061a1b6dc2682c1beace03942d86fd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2013 16:10:45 -0700 Subject: [PATCH 38/39] fix sdl inclusion --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index 30cc6873e7ddf..8c528a462852f 100755 --- a/emcc +++ b/emcc @@ -1333,7 +1333,7 @@ try: return build_libcxx(os.path.join('system', 'lib'), 'sdl.bc', ['sdl.cpp']) def apply_sdl(need): - return 'malloc' not in all_needed or 'free' not in all_needed + return 'SDL_Init' in all_needed and ('malloc' not in all_needed or 'free' not in all_needed) # Settings this in the environment will avoid checking dependencies and make building big projects a little faster force = os.environ.get('EMCC_FORCE_STDLIBS') From 06a8c252d94f34a3729aaefe8cb89fbe1a877a57 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 7 May 2013 16:10:52 -0700 Subject: [PATCH 39/39] switch to le32 target by default --- src/settings.js | 4 ++-- tests/runner.py | 4 ++-- tools/shared.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/settings.js b/src/settings.js index ba1f6a834984e..d029598a91a42 100644 --- a/src/settings.js +++ b/src/settings.js @@ -17,8 +17,8 @@ var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. // // Changing this from the default of 4 is deprecated. -var TARGET_X86 = 1; // For le32-unknown-nacl -var TARGET_LE32 = 0; // For i386-pc-linux-gnu +var TARGET_X86 = 0; // For i386-pc-linux-gnu +var TARGET_LE32 = 1; // For le32-unknown-nacl var CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values. // Decreases performance with additional runtime checks. Might not be diff --git a/tests/runner.py b/tests/runner.py index 0d8878c3c252a..29c8ca7db3850 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -457,7 +457,7 @@ def setup_runtimelink_test(self): if len(sys.argv) == 2 and 'ALL.' in sys.argv[1]: ignore, test = sys.argv[1].split('.') print 'Running all test modes on test "%s"' % test - sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 'asm2le32.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] + sys.argv = [sys.argv[0], 'default.'+test, 'o1.'+test, 'o2.'+test, 'asm1.'+test, 'asm2.'+test, 'asm2g.'+test, 'asm2x86.'+test, 's_0_0.'+test, 's_0_1.'+test, 's_1_0.'+test, 's_1_1.'+test] class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. @@ -9345,7 +9345,7 @@ def setUp(self): exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "CHECK_HEAP_ALIGN=1"])') exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"])') exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])') - exec('''asm2le32 = make_run("asm2le32", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "le32-unknown-nacl"}')''') + exec('''asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}')''') # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ diff --git a/tools/shared.py b/tools/shared.py index 2bd219a982d9b..5a9860dbab7b2 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -295,7 +295,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.4.2' +EMSCRIPTEN_VERSION = '1.4.3' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() @@ -495,7 +495,7 @@ def clean_temp(): # Target choice. Must be synced with src/settings.js (TARGET_*) def get_llvm_target(): - return os.environ.get('EMCC_LLVM_TARGET') or 'i386-pc-linux-gnu' # 'le32-unknown-nacl' + return os.environ.get('EMCC_LLVM_TARGET') or 'le32-unknown-nacl' # 'i386-pc-linux-gnu' LLVM_TARGET = get_llvm_target() try: