From dfe129373a1daaf946e490e49522ca544f9ba7d0 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Sun, 25 Oct 2020 20:30:25 -0400 Subject: [PATCH] fix float loads, add dgo loading to game test (#101) * fix float loads, add dgo loading to game test * build and load dgos in order --- decompiler/config/all-types.gc | 8 +-- doc/changelog.md | 3 +- goal_src/engine/math/vector-h.gc | 51 +++++++++++++++---- goalc/compiler/IR.cpp | 8 ++- goalc/compiler/Val.cpp | 16 ++++++ goalc/compiler/Val.h | 1 + .../with_game/test-build-game.gc | 2 - .../with_game/test-load-game.gc | 2 + .../with_game/test-vector-dot.gc | 14 +++++ test/goalc/test_with_game.cpp | 13 +++-- 10 files changed, 96 insertions(+), 22 deletions(-) create mode 100644 test/goalc/source_templates/with_game/test-load-game.gc create mode 100644 test/goalc/source_templates/with_game/test-vector-dot.gc diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 3ec673dd38..8126b41de6 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -31214,7 +31214,7 @@ ;;(define-extern vector4ub object) ;; unknown type ;;(define-extern vector2w object) ;; unknown type ;;(define-extern isphere object) ;; unknown type -(define-extern vector-dot-vu function) +(define-extern vector-dot-vu (function vector vector float)) ;;(define-extern vertical-planes object) ;; unknown type ;;(define-extern cylinder object) ;; unknown type ;;(define-extern *x-vector* object) ;; unknown type @@ -31229,7 +31229,7 @@ ;;(define-extern cylinder-flat object) ;; unknown type ;;(define-extern plane object) ;; unknown type ;;(define-extern vector3s object) ;; unknown type -(define-extern vector-dot function) +(define-extern vector-dot (function vector vector float)) ;;(define-extern *zero-vector* object) ;; unknown type ;;(define-extern vector4h object) ;; unknown type ;;(define-extern vector4w object) ;; unknown type @@ -31240,13 +31240,13 @@ ;;(define-extern vector4b object) ;; unknown type ;;(define-extern vector4w-4 object) ;; unknown type ;;(define-extern vertical-planes-array object) ;; unknown type -(define-extern vector4-dot function) +(define-extern vector4-dot (function vector vector float)) ;;(define-extern vector2uh object) ;; unknown type ;;(define-extern sphere object) ;; unknown type ;;(define-extern vector3h object) ;; unknown type ;;(define-extern vector4w-3 object) ;; unknown type (define-extern vector+! function) -(define-extern vector4-dot-vu function) +(define-extern vector4-dot-vu (function vector vector float)) ;;(define-extern box8s object) ;; unknown type ;;(define-extern vector3w object) ;; unknown type (define-extern vector-reset! function) diff --git a/doc/changelog.md b/doc/changelog.md index aa7ea5a5dc..9ad47ebc04 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -43,4 +43,5 @@ - Creating a field of 128-bit value type no longer causes a compiler crash - 128-bit fields are inspected as `` -- Static fields can now contain floating point values \ No newline at end of file +- Static fields can now contain floating point values +- Fixed a bug where loading a float from an object and immediately using it math would cause a compiler crash \ No newline at end of file diff --git a/goal_src/engine/math/vector-h.gc b/goal_src/engine/math/vector-h.gc index 5ca9f09394..2ca68d9e38 100644 --- a/goal_src/engine/math/vector-h.gc +++ b/goal_src/engine/math/vector-h.gc @@ -419,15 +419,46 @@ ;; todo dot, dot-vu, 4-dot, 4-dot-vu, +!, -!, zero!, reset!, copy! -; (defun vector-dot ((a vector) (b vector)) -; "Take the dot product of two vectors. -; Only does the x, y, z compoments" -; (let ((result 0.)) -; (+! result (* (-> a x) (-> b x))) -; (+! result (* (-> a y) (-> b y))) -; (+! result (* (-> a z) (-> b z))) -; ) -; result -; ) +(defun vector-dot ((a vector) (b vector)) + "Take the dot product of two vectors. + Only does the x, y, z compoments. + Originally handwritten assembly to space out loads and use FPU accumulator" + (declare (inline)) + (let ((result 0.)) + (+! result (* (-> a x) (-> b x))) + (+! result (* (-> a y) (-> b y))) + (+! result (* (-> a z) (-> b z))) + result + ) + ) + +(defun vector-dot-vu ((a vector) (b vector)) + "Take the dot product of two vectors. + Only does the x, y, z components. + Originally implemented using VU macro ops" + (declare (inline)) + (vector-dot a b) + ) + +(defun vector4-dot ((a vector) (b vector)) + "Take the dot product of two vectors. + Does the x, y, z, and w compoments" + (declare (inline)) + (let ((result 0.)) + (+! result (* (-> a x) (-> b x))) + (+! result (* (-> a y) (-> b y))) + (+! result (* (-> a z) (-> b z))) + (+! result (* (-> a w) (-> b w))) + result + ) + ) + +(defun vector-dot-vu ((a vector) (b vector)) + "Take the dot product of two vectors. + Does the x, y, z, and w compoments + Originally implemented using VU macro ops" + (declare (inline)) + (vector4-dot a b) + ) (define *zero-vector* (new 'static 'vector :x 0. :y 0. :z 0. :w 0.)) \ No newline at end of file diff --git a/goalc/compiler/IR.cpp b/goalc/compiler/IR.cpp index f5594b599a..dc4656df7f 100644 --- a/goalc/compiler/IR.cpp +++ b/goalc/compiler/IR.cpp @@ -718,8 +718,14 @@ void IR_LoadConstOffset::do_codegen(emitter::ObjectGenerator* gen, emitter::gRegInfo.get_offset_reg(), m_offset, m_info.size, m_info.sign_extend), irec); + } else if (m_dest->ireg().kind == emitter::RegKind::XMM && m_info.size == 4 && + m_info.sign_extend == false && m_info.reg == ::RegKind::FLOAT) { + gen->add_instr( + IGen::load_goal_xmm32(get_reg(m_dest, allocs, irec), get_reg(m_base, allocs, irec), + emitter::gRegInfo.get_offset_reg(), m_offset), + irec); } else { - throw std::runtime_error("IR_LoadConstOffset::do_codegen xmm not supported"); + throw std::runtime_error("IR_LoadConstOffset::do_codegen not supported"); } } diff --git a/goalc/compiler/Val.cpp b/goalc/compiler/Val.cpp index 7160dffc37..6dab69ffa2 100644 --- a/goalc/compiler/Val.cpp +++ b/goalc/compiler/Val.cpp @@ -25,6 +25,7 @@ RegVal* Val::to_xmm(Env* fe) { if (rv->ireg().kind == emitter::RegKind::XMM) { return rv; } else { + assert(false); throw std::runtime_error("Register is not an XMM[0-15] register."); } } @@ -127,6 +128,21 @@ RegVal* MemoryDerefVal::to_reg(Env* fe) { } } +RegVal* MemoryDerefVal::to_xmm(Env* fe) { + auto base_as_co = dynamic_cast(base); + if (base_as_co) { + auto re = fe->make_xmm(coerce_to_reg_type(m_ts)); + fe->emit(std::make_unique(re, base_as_co->offset, + base_as_co->base->to_gpr(fe), info)); + return re; + } else { + auto re = fe->make_xmm(coerce_to_reg_type(m_ts)); + auto addr = base->to_gpr(fe); + fe->emit(std::make_unique(re, 0, addr, info)); + return re; + } +} + RegVal* AliasVal::to_reg(Env* fe) { auto as_old_type = base->to_reg(fe); auto result = fe->make_ireg(m_ts, as_old_type->ireg().kind); diff --git a/goalc/compiler/Val.h b/goalc/compiler/Val.h index 67fe8874eb..48ad8adec0 100644 --- a/goalc/compiler/Val.h +++ b/goalc/compiler/Val.h @@ -184,6 +184,7 @@ class MemoryDerefVal : public Val { : Val(std::move(ts)), base(_base), info(_info) {} std::string print() const override { return "[" + base->print() + "]"; } RegVal* to_reg(Env* fe) override; + RegVal* to_xmm(Env* fe) override; Val* base = nullptr; MemLoadInfo info; }; diff --git a/test/goalc/source_templates/with_game/test-build-game.gc b/test/goalc/source_templates/with_game/test-build-game.gc index fe473f2e15..133b41135f 100644 --- a/test/goalc/source_templates/with_game/test-build-game.gc +++ b/test/goalc/source_templates/with_game/test-build-game.gc @@ -1,4 +1,2 @@ (build-game) -(dgo-load "kernel" global #xf #x200000) ; todo, remove once kernel loads itself. -(dgo-load "game" global #xf #x200000) 1 \ No newline at end of file diff --git a/test/goalc/source_templates/with_game/test-load-game.gc b/test/goalc/source_templates/with_game/test-load-game.gc new file mode 100644 index 0000000000..7937cbd9f4 --- /dev/null +++ b/test/goalc/source_templates/with_game/test-load-game.gc @@ -0,0 +1,2 @@ +(dgo-load "kernel" global #xf #x200000) ; todo, remove once kernel loads itself. +(dgo-load "game" global #xf #x200000) \ No newline at end of file diff --git a/test/goalc/source_templates/with_game/test-vector-dot.gc b/test/goalc/source_templates/with_game/test-vector-dot.gc new file mode 100644 index 0000000000..22f115ad42 --- /dev/null +++ b/test/goalc/source_templates/with_game/test-vector-dot.gc @@ -0,0 +1,14 @@ +(start-test "vector-dot") + +(let ((a (new 'global 'vector)) + (b (new 'global 'vector))) + (set! (-> a x) 1.) + (set! (-> a y) 2.) + (set! (-> a z) 3.) + (set! (-> b x) 2.) + (set! (-> b y) 3.) + (set! (-> b z) 4.) + (expect-true (= 20.0 (vector-dot-vu a b))) + ) + +(finish-test) \ No newline at end of file diff --git a/test/goalc/test_with_game.cpp b/test/goalc/test_with_game.cpp index 069576f048..085f67bbed 100644 --- a/test/goalc/test_with_game.cpp +++ b/test/goalc/test_with_game.cpp @@ -26,15 +26,18 @@ struct WithGameParam { class WithGameTests : public testing::TestWithParam { public: static void SetUpTestSuite() { + compiler.run_test_no_load("test/goalc/source_templates/with_game/test-build-game.gc"); + runtime_thread = std::thread((GoalTest::runtime_with_kernel)); + runner.c = &compiler; + + compiler.run_test("test/goalc/source_templates/with_game/test-load-game.gc"); + try { - compiler.run_test_no_load("test/goalc/source_templates/with_game/test-build-game.gc"); + compiler.run_test("test/goalc/source_templates/with_game/test-build-game.gc"); } catch (std::exception& e) { fprintf(stderr, "caught exception %s\n", e.what()); EXPECT_TRUE(false); } - - runtime_thread = std::thread((GoalTest::runtime_with_kernel)); - runner.c = &compiler; } static void TearDownTestSuite() { @@ -131,6 +134,8 @@ TEST_F(WithGameTests, All) { get_test_pass_string("new-static-structure-integers", 7)); runner.run_static_test(env, testCategory, "test-new-static-basic.gc", get_test_pass_string("new-static-basic", 9)); + runner.run_static_test(env, testCategory, "test-vector-dot.gc", + get_test_pass_string("vector-dot", 1)); } TEST(TypeConsistency, TypeConsistency) {