From eee8390ec04ad258ce282e6a4cf066f08c6090f1 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Mon, 26 Jul 2021 21:39:05 -0400 Subject: [PATCH] support inline arrays on stack (#726) --- decompiler/IR2/AtomicOpTypeAnalysis.cpp | 3 +- decompiler/IR2/Env.cpp | 31 ++++++++++++++++--- decompiler/IR2/Form.cpp | 4 +++ docs/markdown/progress-notes/changelog.md | 5 ++- goal_src/kernel/gcommon.gc | 2 +- goal_src/kernel/gkernel.gc | 2 +- goalc/compiler/compilation/Type.cpp | 20 +++++++++--- .../source_templates/kernel/kernel-test.gc | 8 ++--- .../variables/stack-array-align.gc | 4 +-- .../variables/stack-ints-2.gc | 2 +- .../source_templates/variables/stack-ints.gc | 8 ++--- .../with_game/test-approx-pi-stack.gc | 16 +++++----- .../with_game/test-bitfield-and-enum-types.gc | 12 +++---- .../with_game/test-function128.gc | 2 +- .../with_game/test-game-text.gc | 4 +-- .../with_game/test-i128-simple.gc | 6 ++-- .../with_game/test-pand-por-pnor.gc | 6 ++-- .../source_templates/with_game/test-pextlw.gc | 14 ++++----- .../with_game/test-size-of.gc | 4 +-- .../with_game/test-stack-inline-array.gc | 13 ++++++++ .../source_templates/with_game/test-trig.gc | 18 +++++------ test/goalc/test_with_game.cpp | 6 ++++ 22 files changed, 124 insertions(+), 66 deletions(-) create mode 100644 test/goalc/source_templates/with_game/test-stack-inline-array.gc diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 6aaa1eeac..90338f7d8 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -261,7 +261,8 @@ TP_Type get_stack_type_at_constant_offset(int offset, if (offset == structure.hint.stack_offset) { // special case just getting the variable - if (structure.hint.container_type == StackStructureHint::ContainerType::NONE) { + if (structure.hint.container_type == StackStructureHint::ContainerType::NONE || + structure.hint.container_type == StackStructureHint::ContainerType::INLINE_ARRAY) { return TP_Type::make_from_ts(coerce_to_reg_type(structure.ref_type)); } } diff --git a/decompiler/IR2/Env.cpp b/decompiler/IR2/Env.cpp index 4fbca41a1..2db0a059a 100644 --- a/decompiler/IR2/Env.cpp +++ b/decompiler/IR2/Env.cpp @@ -518,12 +518,12 @@ void Env::set_stack_structure_hints(const std::vector& hints for (auto& hint : hints) { StackStructureEntry entry; entry.hint = hint; - // parse the type spec. - TypeSpec base_typespec = dts->parse_type_spec(hint.element_type); - auto type_info = dts->ts.lookup_type(base_typespec); switch (hint.container_type) { - case StackStructureHint::ContainerType::NONE: + case StackStructureHint::ContainerType::NONE: { + // parse the type spec. + TypeSpec base_typespec = dts->parse_type_spec(hint.element_type); + auto type_info = dts->ts.lookup_type(base_typespec); // just a plain object on the stack. if (!type_info->is_reference()) { throw std::runtime_error( @@ -540,8 +540,29 @@ void Env::set_stack_structure_hints(const std::vector& hints entry.ref_type.print(), entry.hint.stack_offset, type_info->get_in_memory_alignment()); } + } break; - break; + case StackStructureHint::ContainerType::INLINE_ARRAY: { + TypeSpec base_typespec = dts->parse_type_spec(hint.element_type); + auto type_info = dts->ts.lookup_type(base_typespec); + if (!type_info->is_reference()) { + throw std::runtime_error( + fmt::format("Stack inline-array element type {} is not a reference and cannot be " + "stored in an inline-array. Use an array instead.", + base_typespec.print())); + } + + entry.ref_type = TypeSpec("inline-array", {TypeSpec(base_typespec)}); + entry.size = 1; // we assume that there is no constant propagation into this array and + // make this only trigger in get_stack_type if we hit exactly. + // sanity check the alignment + if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) != + entry.hint.stack_offset) { + lg::error("Misaligned stack variable of type {} offset {} required align {}\n", + entry.ref_type.print(), entry.hint.stack_offset, + type_info->get_in_memory_alignment()); + } + } break; default: assert(false); } diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index a846320d5..428e65580 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -2617,6 +2617,10 @@ goos::Object StackStructureDefElement::to_form_internal(const Env&) const { case StackStructureHint::ContainerType::NONE: return pretty_print::build_list( fmt::format("new 'stack-no-clear '{}", m_entry.ref_type.print())); + case StackStructureHint::ContainerType::INLINE_ARRAY: + return pretty_print::build_list(fmt::format("new 'stack-no-clear 'inline-array '{} {}", + m_entry.ref_type.get_single_arg().print(), + m_entry.hint.container_size)); default: assert(false); } diff --git a/docs/markdown/progress-notes/changelog.md b/docs/markdown/progress-notes/changelog.md index c76e93a3d..a74af4956 100644 --- a/docs/markdown/progress-notes/changelog.md +++ b/docs/markdown/progress-notes/changelog.md @@ -181,4 +181,7 @@ - `meters`, `degrees`, and `seconds` types have been added. - Bitfields with `symbol` fields used in an immediate `(new 'static ...)` can now define the symbol in the `new` form. - Bitfields with `float` fields used in an immediate `(new 'static ...)` in code can use a non-constant floating point value. -- Multiple variables assigned to the same register using `:reg` in `rlet` (or overlapping with `self` in a behavior) will now be merged to a single variable instead of causing a compiler error. Variables will have their own type, but they will all be an alias of the same exact register. \ No newline at end of file +- Multiple variables assigned to the same register using `:reg` in `rlet` (or overlapping with `self` in a behavior) will now be merged to a single variable instead of causing a compiler error. Variables will have their own type, but they will all be an alias of the same exact register. +- Stack arrays of uint128 will now be 16-byte aligned instead of sometimes only 8. +- Inline arrays of structures are now allowed with `stack-no-clear`. +- Creating arrays on the stack now must be done with `stack-no-clear` as they are not memset to 0 or constructed in any way. \ No newline at end of file diff --git a/goal_src/kernel/gcommon.gc b/goal_src/kernel/gcommon.gc index 60a0afcf2..307b321cf 100644 --- a/goal_src/kernel/gcommon.gc +++ b/goal_src/kernel/gcommon.gc @@ -266,7 +266,7 @@ (defmacro print128 (value &key (stream #t)) "Print a 128-bit value" - `(let ((temp (new 'stack 'array 'uint64 2))) + `(let ((temp (new 'stack-no-clear 'array 'uint64 2))) (set! (-> (the (pointer uint128) temp)) ,value) (format ,stream "#x~16X~16X" (-> temp 1) (-> temp 0)) ) diff --git a/goal_src/kernel/gkernel.gc b/goal_src/kernel/gkernel.gc index 1fac1b5bf..b6665ae0e 100644 --- a/goal_src/kernel/gkernel.gc +++ b/goal_src/kernel/gkernel.gc @@ -2265,7 +2265,7 @@ This will then return the value of the function you called!" (rlet ((pp :reg r13 :type process)) - (let ((param-array (new 'stack 'array 'uint64 6)) + (let ((param-array (new 'stack-no-clear 'array 'uint64 6)) ) ;; copy params to the stack. diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index b617eeb0a..8ad02235b 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -3,6 +3,7 @@ #include "common/type_system/defenum.h" #include "common/type_system/deftype.h" #include "goalc/emitter/CallingConvention.h" +#include "common/util/math_util.h" namespace { @@ -1022,6 +1023,9 @@ Val* Compiler::compile_stack_new(const goos::Object& form, auto type_of_object = parse_typespec(unquote(type)); auto fe = get_parent_env_of_type(env); if (type_of_object == TypeSpec("inline-array") || type_of_object == TypeSpec("array")) { + if (call_constructor) { + throw_compiler_error(form, "Constructing stack arrays is not yet supported"); + } bool is_inline = type_of_object == TypeSpec("inline-array"); auto elt_type = quoted_sym_as_string(pair_car(*rest)); rest = &pair_cdr(*rest); @@ -1050,16 +1054,22 @@ Val* Compiler::compile_stack_new(const goos::Object& form, if (!info.can_deref) { throw_compiler_error(form, "Cannot make an {} of {}\n", type_of_object.print(), ts.print()); } - + auto type_info = m_ts.lookup_type(ts.get_single_arg()); if (!m_ts.lookup_type(elt_type)->is_reference()) { // not a reference type int size_in_bytes = info.stride * constant_count; - auto addr = fe->allocate_stack_variable(ts, size_in_bytes); + auto addr = fe->allocate_aligned_stack_variable(ts, size_in_bytes, + type_info->get_in_memory_alignment()); return addr; } - // todo - throw_compiler_error(form, "Static array of type {} is not yet supported.", ts.print()); - return get_none(); + + int stride = + align(type_info->get_size_in_memory(), type_info->get_inline_array_stride_alignment()); + assert(stride == info.stride); + + int size_in_bytes = info.stride * constant_count; + auto addr = fe->allocate_aligned_stack_variable(ts, size_in_bytes, stride); + return addr; } else { auto ti = m_ts.lookup_type(type_of_object); diff --git a/test/goalc/source_templates/kernel/kernel-test.gc b/test/goalc/source_templates/kernel/kernel-test.gc index a3098f7a2..574daad8e 100644 --- a/test/goalc/source_templates/kernel/kernel-test.gc +++ b/test/goalc/source_templates/kernel/kernel-test.gc @@ -3,7 +3,7 @@ (format #t "TARGET FUNCTION ~D ~D ~D~%" a0 a1 a2) (format #t "~D ~D ~D~%" a3 a4 a5) - (let ((stack-arr (new 'stack 'array 'uint8 12))) + (let ((stack-arr (new 'stack-no-clear 'array 'uint8 12))) (format #t "Stack Alignemnt ~D/16~%" (logand 15 (the uint stack-arr))) ) @@ -28,7 +28,7 @@ ) (defun target-function-2 () - (let ((stack-var (new 'stack 'array 'int32 1))) + (let ((stack-var (new 'stack-no-clear 'array 'int32 1))) (set! (-> stack-var) 0) (countdown (i 10) (format #t "proc2: ~D~%" (-> stack-var)) @@ -61,7 +61,7 @@ (defun init-child-proc (a0 a1 a2 a3 a4 a5) (format #t "Args: ~D ~D ~D~%" a0 a1 a2) (format #t "~D ~D ~D~%" a3 a4 a5) - (let ((stack-arr (new 'stack 'array 'uint8 12))) + (let ((stack-arr (new 'stack-no-clear 'array 'uint8 12))) (format #t "Stack Alignemnt ~D/16~%" (logand 15 (the uint stack-arr))) ) (if (eq? a0 (the int 0)) @@ -189,4 +189,4 @@ ) ) - ) \ No newline at end of file + ) diff --git a/test/goalc/source_templates/variables/stack-array-align.gc b/test/goalc/source_templates/variables/stack-array-align.gc index 77658d63e..a07fada1b 100644 --- a/test/goalc/source_templates/variables/stack-array-align.gc +++ b/test/goalc/source_templates/variables/stack-array-align.gc @@ -1,7 +1,7 @@ (defun stack-test () - (let ((arr (new 'stack 'array 'uint8 12))) + (let ((arr (new 'stack-no-clear 'array 'uint8 12))) (logand #b1111 (the uint (&-> arr 3))) ) ) -(stack-test) \ No newline at end of file +(stack-test) diff --git a/test/goalc/source_templates/variables/stack-ints-2.gc b/test/goalc/source_templates/variables/stack-ints-2.gc index 54bc60c14..76e96266e 100644 --- a/test/goalc/source_templates/variables/stack-ints-2.gc +++ b/test/goalc/source_templates/variables/stack-ints-2.gc @@ -1,4 +1,4 @@ -(let* ((x (new 'stack 'array 'int8 1)) +(let* ((x (new 'stack-no-clear 'array 'int8 1)) (x-addr (the uint x))) (if (and (> x-addr #x7ffff00) (< x-addr #x7ffffff)) diff --git a/test/goalc/source_templates/variables/stack-ints.gc b/test/goalc/source_templates/variables/stack-ints.gc index 2f32d679a..69847701e 100644 --- a/test/goalc/source_templates/variables/stack-ints.gc +++ b/test/goalc/source_templates/variables/stack-ints.gc @@ -1,9 +1,9 @@ -(let ((x (new 'stack 'array 'int32 1)) - (y (new 'stack 'array 'int8 2)) - (z (new 'stack 'array 'int8 1))) +(let ((x (new 'stack-no-clear 'array 'int32 1)) + (y (new 'stack-no-clear 'array 'int8 2)) + (z (new 'stack-no-clear 'array 'int8 1))) (set! (-> x) 10) (set! (-> z) 0) (set! (-> y) #xfffffffff) (set! (-> y 1) 3) (+ (-> x) (-> y) (-> z) (-> y 1)) - ) \ No newline at end of file + ) diff --git a/test/goalc/source_templates/with_game/test-approx-pi-stack.gc b/test/goalc/source_templates/with_game/test-approx-pi-stack.gc index 153d2666c..6fd14d03e 100644 --- a/test/goalc/source_templates/with_game/test-approx-pi-stack.gc +++ b/test/goalc/source_templates/with_game/test-approx-pi-stack.gc @@ -2,8 +2,8 @@ (start-test "approx-pi-stack") (defun test-approx-pi-stack ((res integer)) - (let ((rad (new 'stack 'array 'int32 1)) - (count (new 'stack 'array 'uint32 1))) + (let ((rad (new 'stack-no-clear 'array 'int32 1)) + (count (new 'stack-no-clear 'array 'uint32 1))) (set! (-> rad) (* res res)) (set! (-> count) 0) @@ -26,11 +26,11 @@ (defun test-approx-pi-float-stack ((res float)) - (let* ((rad (new 'stack 'array 'float 1)) - (count (new 'stack 'array 'float 1)) - (x (new 'stack 'array 'float 1)) - (y (new 'stack 'array 'float 1)) - (scale (new 'stack 'array 'float 1))) + (let* ((rad (new 'stack-no-clear 'array 'float 1)) + (count (new 'stack-no-clear 'array 'float 1)) + (x (new 'stack-no-clear 'array 'float 1)) + (y (new 'stack-no-clear 'array 'float 1)) + (scale (new 'stack-no-clear 'array 'float 1))) (set! (-> rad) (* res res)) (set! (-> count) 0.0) (set! (-> x) 0.0) @@ -56,4 +56,4 @@ (expect-true (< approx-pi 3.15)) ) -(finish-test) \ No newline at end of file +(finish-test) diff --git a/test/goalc/source_templates/with_game/test-bitfield-and-enum-types.gc b/test/goalc/source_templates/with_game/test-bitfield-and-enum-types.gc index bc735ab0c..c8ffb7740 100644 --- a/test/goalc/source_templates/with_game/test-bitfield-and-enum-types.gc +++ b/test/goalc/source_templates/with_game/test-bitfield-and-enum-types.gc @@ -38,7 +38,7 @@ (ens test-enum 12)) ) -(let ((obj (new 'stack 'enum-bitfield-test-type))) +(let ((obj (new 'stack-no-clear 'enum-bitfield-test-type))) (format #t "bitfield spacing: ~d~%" (&- (&-> obj bf1) (&-> obj bf0))) (format #t "enum spacing: ~d~%" (&- (&-> obj en1) (&-> obj en0))) (format #t "bitfield array spacing: ~d~%" (&- (&-> obj bfs 1) (&-> obj bfs 0))) @@ -46,7 +46,7 @@ ) (defun function-enum-test ((x test-enum)) - (let ((obj (new 'stack 'enum-bitfield-test-type))) + (let ((obj (new 'stack-no-clear 'enum-bitfield-test-type))) (set! (-> obj en0) x) (set! (-> obj ens 1) x) ) @@ -54,15 +54,15 @@ ) (defun function-bitfield-test ((x test-bitfield)) - (let ((obj (new 'stack 'enum-bitfield-test-type))) + (let ((obj (new 'stack-no-clear 'enum-bitfield-test-type))) (set! (-> obj bf0) x) (set! (-> obj bfs 1) x) ) (new 'static 'test-bitfield :f1 1) ) -(let ((obj (new 'stack 'enum-bitfield-test-type)) - (mem (new 'stack 'array 'uint8 12)) +(let ((obj (new 'stack-no-clear 'enum-bitfield-test-type)) + (mem (new 'stack-no-clear 'array 'uint8 12)) ) (set! (-> obj bf0) (function-bitfield-test (new 'static 'test-bitfield :f1 1))) (set! (-> obj bf0) (function-bitfield-test (the test-bitfield 1))) @@ -77,4 +77,4 @@ ) -(format #t "sizes: ~d ~d~%" (size-of test-enum) (size-of test-bitfield)) \ No newline at end of file +(format #t "sizes: ~d ~d~%" (size-of test-enum) (size-of test-bitfield)) diff --git a/test/goalc/source_templates/with_game/test-function128.gc b/test/goalc/source_templates/with_game/test-function128.gc index c78e5cf70..a4323b2ce 100644 --- a/test/goalc/source_templates/with_game/test-function128.gc +++ b/test/goalc/source_templates/with_game/test-function128.gc @@ -11,7 +11,7 @@ ) (defun test-print-sound-name-chars ((arg0 int) (name sound-name) (arg2 int)) - (let ((mem (new 'stack 'array 'uint8 16))) + (let ((mem (new 'stack-no-clear 'array 'uint8 16))) (set! (-> (the (pointer sound-name) mem)) name) (let ((i 0)) (while (and (< i 16) (nonzero? (-> mem i))) diff --git a/test/goalc/source_templates/with_game/test-game-text.gc b/test/goalc/source_templates/with_game/test-game-text.gc index 461745555..cd2965507 100644 --- a/test/goalc/source_templates/with_game/test-game-text.gc +++ b/test/goalc/source_templates/with_game/test-game-text.gc @@ -13,7 +13,7 @@ (sync *load-str-rpc* '#t) - (let* ((got-length (new 'stack 'array 'int32 1)) + (let* ((got-length (new 'stack-no-clear 'array 'int32 1)) (status (str-load-status got-length))) ;(format #t "Status is ~A, length ~D~%" status (-> got-length)) @@ -41,4 +41,4 @@ (expect-true (= 5 (length (-> text data 1 text)))) ) -(finish-test) \ No newline at end of file +(finish-test) diff --git a/test/goalc/source_templates/with_game/test-i128-simple.gc b/test/goalc/source_templates/with_game/test-i128-simple.gc index 35d5e46a7..29de649a4 100644 --- a/test/goalc/source_templates/with_game/test-i128-simple.gc +++ b/test/goalc/source_templates/with_game/test-i128-simple.gc @@ -20,8 +20,8 @@ result ) -(let ((arr (new 'stack 'array 'uint8 128)) - (arr2 (new 'stack 'array 'uint8 128))) +(let ((arr (new 'stack-no-clear 'array 'uint8 128)) + (arr2 (new 'stack-no-clear 'array 'uint8 128))) (dotimes (i 128) (set! (-> arr i) i) (set! (-> arr2 (- 127 i)) i) @@ -46,4 +46,4 @@ (set! x 0) (set! z y) z - ) \ No newline at end of file + ) diff --git a/test/goalc/source_templates/with_game/test-pand-por-pnor.gc b/test/goalc/source_templates/with_game/test-pand-por-pnor.gc index e25d6a1c7..067974882 100644 --- a/test/goalc/source_templates/with_game/test-pand-por-pnor.gc +++ b/test/goalc/source_templates/with_game/test-pand-por-pnor.gc @@ -1,7 +1,7 @@ -(let ((v1 (new 'stack 'array 'uint8 16)) - (v2 (new 'stack 'array 'uint8 16)) - (v3 (new 'stack 'array 'uint8 16)) +(let ((v1 (new 'stack-no-clear 'array 'uint8 16)) + (v2 (new 'stack-no-clear 'array 'uint8 16)) + (v3 (new 'stack-no-clear 'array 'uint8 16)) ) ;; initialize stack arrays diff --git a/test/goalc/source_templates/with_game/test-pextlw.gc b/test/goalc/source_templates/with_game/test-pextlw.gc index cfb95739f..4bfd0c769 100644 --- a/test/goalc/source_templates/with_game/test-pextlw.gc +++ b/test/goalc/source_templates/with_game/test-pextlw.gc @@ -1,6 +1,6 @@ -(let ((v1 (new 'stack 'array 'uint8 16)) - (v2 (new 'stack 'array 'uint8 16)) - (v3 (new 'stack 'array 'uint8 16)) +(let ((v1 (new 'stack-no-clear 'array 'uint8 16)) + (v2 (new 'stack-no-clear 'array 'uint8 16)) + (v3 (new 'stack-no-clear 'array 'uint8 16)) ) ;; initialize stack arrays @@ -30,8 +30,8 @@ (print128 v3-quad) (format #t "~%") ) - (let ((s1 (new 'stack 'array 'uint32 4)) - (s2 (new 'stack 'array 'uint32 4))) + (let ((s1 (new 'stack-no-clear 'array 'uint32 4)) + (s2 (new 'stack-no-clear 'array 'uint32 4))) (set! (-> s1 0) #xdeadbeef) (set! (-> s1 1) #x12312323) (set! (-> s1 2) #x11112222) @@ -52,8 +52,8 @@ ) ) - (let ((s1 (new 'stack 'array 'uint32 4)) - (s2 (new 'stack 'array 'uint32 4))) + (let ((s1 (new 'stack-no-clear 'array 'uint32 4)) + (s2 (new 'stack-no-clear 'array 'uint32 4))) (set! (-> s1 0) #x300) (set! (-> s1 1) #x3) (set! (-> s1 2) #x100) diff --git a/test/goalc/source_templates/with_game/test-size-of.gc b/test/goalc/source_templates/with_game/test-size-of.gc index 3e40be777..f690d1ab4 100644 --- a/test/goalc/source_templates/with_game/test-size-of.gc +++ b/test/goalc/source_templates/with_game/test-size-of.gc @@ -3,7 +3,7 @@ ;; note - this makes some assumptions about how the OpenGOAL compiler will lay things out ;; on the stack. -(let ((x (new 'stack 'array 'uint8 (size-of dma-bucket))) - (y (new 'stack 'array 'uint 1))) +(let ((x (new 'stack-no-clear 'array 'uint8 (size-of dma-bucket))) + (y (new 'stack-no-clear 'array 'uint 1))) (format #t "size of stack array is ~d~%" (&- y x)) ) diff --git a/test/goalc/source_templates/with_game/test-stack-inline-array.gc b/test/goalc/source_templates/with_game/test-stack-inline-array.gc new file mode 100644 index 000000000..e564363d4 --- /dev/null +++ b/test/goalc/source_templates/with_game/test-stack-inline-array.gc @@ -0,0 +1,13 @@ +(defun test-stack-inline-array () + (let ((t0 (new 'stack-no-clear 'array 'int32 1)) + (ta (new 'stack-no-clear 'array 'int32 1)) + (t1 (new 'stack-no-clear 'inline-array 'vector 3)) + (t2 (new 'stack-no-clear 'inline-array 'vector 2))) + ;; these are somewhat specific to the current strategy for laying out the stack. + (format #t "#x~X~%" (&- t1 ta)) + (format #t "#x~X~%" (&- t2 t1)) + (set! (-> t1 1 quad) (the-as uint128 0)) + ) + ) + +(test-stack-inline-array) diff --git a/test/goalc/source_templates/with_game/test-trig.gc b/test/goalc/source_templates/with_game/test-trig.gc index 95284214b..2f2606d1a 100644 --- a/test/goalc/source_templates/with_game/test-trig.gc +++ b/test/goalc/source_templates/with_game/test-trig.gc @@ -42,8 +42,8 @@ (format #t "~%") ;; vector-sin-rad! -(let ((in (new 'stack 'vector)) - (out (new 'stack 'vector)) +(let ((in (new 'stack-no-clear 'vector)) + (out (new 'stack-no-clear 'vector)) ) (set-vector! in PI_OVER_6 (- PI_OVER_4) PI_OVER_3 (- PI_OVER_2)) (vector-sin-rad! out in) @@ -59,8 +59,8 @@ (format #t "~%") ;; vector-cos-rad! -(let ((in (new 'stack 'vector)) - (out (new 'stack 'vector)) +(let ((in (new 'stack-no-clear 'vector)) + (out (new 'stack-no-clear 'vector)) ) (set-vector! in PI_OVER_6 (- PI_OVER_4) PI_OVER_3 (- PI_OVER_2)) (vector-cos-rad! out in) @@ -69,9 +69,9 @@ (format #t "~%") ;; vector-sincos-rad! -(let ((in (new 'stack 'vector)) - (out-sin (new 'stack 'vector)) - (out-cos (new 'stack 'vector)) +(let ((in (new 'stack-no-clear 'vector)) + (out-sin (new 'stack-no-clear 'vector)) + (out-cos (new 'stack-no-clear 'vector)) ) (set-vector! in PI_OVER_6 (- PI_OVER_4) PI_OVER_3 (- PI_OVER_2)) (vector-sincos-rad! out-sin out-cos in) @@ -81,7 +81,7 @@ (format #t "~%") ;; sincos-rad! (has cosine bug) -(let ((out (new 'stack 'array 'float 2))) +(let ((out (new 'stack-no-clear 'array 'float 2))) (sincos-rad! out PI_OVER_4) (format #t "~f ~f~%" (-> out 0) (-> out 1)) (sincos-rad! out (- PI_OVER_2)) @@ -91,7 +91,7 @@ ;; sincos! (has cosine bug) (format #t "sincos!~%") -(let ((out (new 'stack 'array 'float 2))) +(let ((out (new 'stack-no-clear 'array 'float 2))) (sincos! out (+ 0.0 (degrees 765))) (format #t "~f ~f~%" (-> out 0) (-> out 1)) (sincos! out (+ (degrees 750) -0.0)) diff --git a/test/goalc/test_with_game.cpp b/test/goalc/test_with_game.cpp index 43aed8bdd..99818a5f3 100644 --- a/test/goalc/test_with_game.cpp +++ b/test/goalc/test_with_game.cpp @@ -816,6 +816,12 @@ TEST_F(WithGameTests, PandPorPnor) { "#x0200000c0a0808080200000402000000\n0\n"}); } +TEST_F(WithGameTests, StackInlineArray) { + runner.run_static_test(env, testCategory, "test-stack-inline-array.gc", + {"#x8\n" + "#x30\n0\n"}); +} + TEST(TypeConsistency, TypeConsistency) { Compiler compiler; compiler.enable_throw_on_redefines();