Change syntax for boxed array to support different length and allocated-length (#568)

* change syntax for boxed array

* fix test and make the flava thing kind of work
This commit is contained in:
water111 2021-06-07 20:22:06 -04:00 committed by GitHub
parent f516737cf7
commit 5b24e43143
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 197 additions and 106 deletions

View file

@ -3359,10 +3359,10 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
if (m_expected_stride == 1) {
// reg0 is idx
auto reg0_matcher =
Matcher::match_or({Matcher::any(0), Matcher::cast("int", Matcher::any_reg(0))});
Matcher::match_or({Matcher::cast("int", Matcher::any(0)), Matcher::any(0)});
// reg1 is base
auto reg1_matcher =
Matcher::match_or({Matcher::any_reg(1), Matcher::cast("int", Matcher::any_reg(1))});
Matcher::match_or({Matcher::cast("int", Matcher::any(1)), Matcher::any(1)});
auto matcher = Matcher::fixed_op(FixedOperatorKind::ADDITION, {reg0_matcher, reg1_matcher});
auto match_result = match(matcher, new_val);
if (!match_result.matched) {
@ -3370,8 +3370,8 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
new_val->to_string(env));
}
auto idx = match_result.maps.forms.at(0);
auto base = match_result.maps.regs.at(1);
assert(idx && base.has_value());
auto base = match_result.maps.forms.at(1);
assert(idx && base);
std::vector<DerefToken> tokens = m_deref_tokens;
for (auto& x : tokens) {
@ -3381,7 +3381,7 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
}
// tokens.push_back(DerefToken::make_int_expr(var_to_form(idx.value(), pool)));
auto deref = pool.alloc_element<DerefElement>(var_to_form(base.value(), pool), false, tokens);
auto deref = pool.alloc_element<DerefElement>(base, false, tokens);
result->push_back(deref);
} else if (is_power_of_two(m_expected_stride, &power_of_two)) {
// (+ (sll (the-as uint a1-0) 2) (the-as int a0-0))

View file

@ -694,19 +694,18 @@ goos::Object decompile_boxed_array(const DecompilerLabel& label,
throw std::runtime_error("Invalid size in decompile_boxed_array");
}
if (size_word_1.data != size_word_2.data) {
throw std::runtime_error("Inconsistent size in decompile_boxed_array");
}
int array_length = size_word_1.data;
int array_allocated_length = size_word_2.data;
auto content_type_info = ts.lookup_type(content_type);
if (content_type_info->is_reference()) {
// easy, stride of 4.
std::vector<goos::Object> result = {
pretty_print::to_symbol("new"), pretty_print::to_symbol("'static"),
pretty_print::to_symbol("'boxed-array"), pretty_print::to_symbol(content_type.print()),
pretty_print::to_symbol(fmt::format("{}", array_length))};
pretty_print::to_symbol("'boxed-array"),
pretty_print::to_symbol(fmt::format(":type {} :length {} :allocated-length {}",
content_type.print(), array_length,
array_allocated_length))};
for (int elt = 0; elt < array_length; elt++) {
auto& word = words.at(label.target_segment).at(first_elt_word_idx + elt);
@ -727,8 +726,10 @@ goos::Object decompile_boxed_array(const DecompilerLabel& label,
// value array
std::vector<goos::Object> result = {
pretty_print::to_symbol("new"), pretty_print::to_symbol("'static"),
pretty_print::to_symbol("'boxed-array"), pretty_print::to_symbol(content_type.print()),
pretty_print::to_symbol(fmt::format("{}", array_length))};
pretty_print::to_symbol("'boxed-array"),
pretty_print::to_symbol(fmt::format(":type {} :length {} :allocated-length {}",
content_type.print(), array_length,
array_allocated_length))};
auto stride = content_type_info->get_size_in_memory();
for (int i = 0; i < array_length; i++) {

View file

@ -19,7 +19,7 @@
)
(define *vif-disasm-table*
(new 'static 'boxed-array vif-disasm-element 34
(new 'static 'boxed-array :type vif-disasm-element :length 34
(new 'static 'vif-disasm-element :mask #x7f :string1 "nop")
(new 'static 'vif-disasm-element :mask #x7f :tag #x1 :print #x2 :string1 "stcycl")
(new 'static 'vif-disasm-element :mask #x7f :tag #x2 :print #x1 :string1 "offset" :string2 "offset")

View file

@ -279,36 +279,36 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define ct32-24-block-table
(new 'static 'boxed-array int32
32 0 1 4 5 16 17 20 21 2 3 6 7 18 19 22 23 8 9 12 13 24 25 28 29 10 11 14 15 26 27 30 31))
(new 'static 'boxed-array :type int32 :length 32
0 1 4 5 16 17 20 21 2 3 6 7 18 19 22 23 8 9 12 13 24 25 28 29 10 11 14 15 26 27 30 31))
(define mz32-24-block-table
(new 'static 'boxed-array int32
32 16 17 20 21 0 1 4 5 18 19 22 23 2 3 6 7 24 25 28 29 8 9 12 13 26 27 30 31 10 11 14 15))
(new 'static 'boxed-array :type int32 :length 32
16 17 20 21 0 1 4 5 18 19 22 23 2 3 6 7 24 25 28 29 8 9 12 13 26 27 30 31 10 11 14 15))
(define ct16-block-table
(new 'static 'boxed-array int32
32 0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15 16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31))
(new 'static 'boxed-array :type int32 :length 32
0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15 16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31))
(define ct16s-block-table
(new 'static 'boxed-array int32
32 0 2 16 18 1 3 17 19 8 10 24 26 9 11 25 27 4 6 20 22 5 7 21 23 12 14 28 30 13 15 29 31))
(new 'static 'boxed-array :type int32 :length 32
0 2 16 18 1 3 17 19 8 10 24 26 9 11 25 27 4 6 20 22 5 7 21 23 12 14 28 30 13 15 29 31))
(define mz16-block-table
(new 'static 'boxed-array int32
32 16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31 0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15))
(new 'static 'boxed-array :type int32 :length 32
16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31 0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15))
(define mz16s-block-table
(new 'static 'boxed-array int32
32 16 18 0 2 17 19 1 3 24 26 8 10 25 27 9 11 20 22 4 6 21 23 5 7 28 30 12 14 29 31 13 15))
(new 'static 'boxed-array :type int32 :length 32
16 18 0 2 17 19 1 3 24 26 8 10 25 27 9 11 20 22 4 6 21 23 5 7 28 30 12 14 29 31 13 15))
(define mt8-block-table
(new 'static 'boxed-array int32
32 0 1 4 5 16 17 20 21 2 3 6 7 18 19 22 23 8 9 12 13 24 25 28 29 10 11 14 15 26 27 30 31))
(new 'static 'boxed-array :type int32 :length 32
0 1 4 5 16 17 20 21 2 3 6 7 18 19 22 23 8 9 12 13 24 25 28 29 10 11 14 15 26 27 30 31))
(define mt4-block-table
(new 'static 'boxed-array int32
32 0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15 16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31))
(new 'static 'boxed-array :type int32 :length 32
0 2 8 10 1 3 9 11 4 6 12 14 5 7 13 15 16 18 24 26 17 19 25 27 20 22 28 30 21 23 29 31))
(defun gs-find-block ((bx int) (by int) (tex-format gs-psm))
"Block index lookup."

View file

@ -14,7 +14,7 @@
:flag-assert #x900000010
)
(define *wind-scales* (new 'static 'boxed-array uint8 32
(define *wind-scales* (new 'static 'boxed-array :type uint8 :length 32
#x2 #x5 #x2 #x3
#x2 #x2 #x3 #x10
#xa #x2 #x4 #x2

View file

@ -6,8 +6,10 @@
;; dgos: GAME, ENGINE
;; maybe euler angle storage orders?
(define EulSafe (new 'static 'boxed-array int32 4 0 1 2 0))
(define EulNext (new 'static 'boxed-array int32 4 1 2 0 1))
(define EulSafe (new 'static 'boxed-array :type int32 :length 4
0 1 2 0))
(define EulNext (new 'static 'boxed-array :type int32 :length 4
1 2 0 1))
;; just uses the same xyzw and data array as vector.
;; the w stores a float that should be an integer that seems to have

View file

@ -126,7 +126,7 @@
;; create a static array with the given values, interpreted as floats.
(defmacro make-float-table (name size vals)
`(define ,name (new 'static 'boxed-array float ,size
`(define ,name (new 'static 'boxed-array :type float :length ,size
,@(apply (lambda (x) `(the-as float ,x)) vals)))
)

View file

@ -34,18 +34,18 @@
)
;; definition for symbol *title-credits-scale*, type (array float)
(define
*title-credits-scale*
(define *title-credits-scale*
(the-as (array float)
(new 'static 'boxed-array float 8 0.9 0.9 0.6 0.6 1.0 0.9 1.1 0.9)
(new 'static 'boxed-array :type float :length 8
0.9 0.9 0.6 0.6 1.0 0.9 1.1 0.9)
)
)
;; definition for symbol *title-credits-spacing*, type (array int32)
(define
*title-credits-spacing*
(define *title-credits-spacing*
(the-as (array int32)
(new 'static 'boxed-array int32 8 15 20 15 15 20 15 20 15)
(new 'static 'boxed-array :type int32 :length 8
15 20 15 15 20 15 20 15)
)
)

View file

@ -36,7 +36,7 @@
)
;; todo, need support for array
(define *text-group-names* (new 'static 'boxed-array string 1 "common"))
(define *text-group-names* (new 'static 'boxed-array :type string :length 1 "common"))
(define *common-text-heap* (new 'global 'kheap))

View file

@ -195,10 +195,11 @@ class Compiler {
Env* env,
bool call_constructor);
StaticResult fill_static_array(const goos::Object& form,
const goos::Object& rest,
bool boxed,
Env* env);
StaticResult fill_static_array(const goos::Object& form, const goos::Object& rest, Env* env);
StaticResult fill_static_boxed_array(const goos::Object& form,
const goos::Object& rest,
Env* env);
StaticResult fill_static_inline_array(const goos::Object& form,
const goos::Object& rest,
@ -212,7 +213,8 @@ class Compiler {
Env* env);
void fill_static_array_inline(const goos::Object& form,
const TypeSpec& content_type,
const std::vector<goos::Object>& args,
goos::Object* args_array,
int args_array_length,
StaticStructure* structure,
int offset,
Env* env);

View file

@ -116,8 +116,8 @@ void Compiler::compile_static_structure_inline(const goos::Object& form,
fill_static_inline_array_inline(field_value, field_info.field.type(), arg_list, structure,
field_offset, env);
} else {
fill_static_array_inline(field_value, field_info.field.type(), arg_list, structure,
field_offset, env);
fill_static_array_inline(field_value, field_info.field.type(), arg_list.data() + 4,
(int)arg_list.size() - 4, structure, field_offset, env);
}
} else if (is_integer(field_info.type)) {
@ -615,9 +615,9 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
}
if (unquote(args.at(1)).as_symbol()->name == "boxed-array") {
return fill_static_array(form, rest, true, env);
return fill_static_boxed_array(form, rest, env);
} else if (unquote(args.at(1)).as_symbol()->name == "array") {
return fill_static_array(form, rest, false, env);
return fill_static_array(form, rest, env);
} else if (unquote(args.at(1)).as_symbol()->name == "inline-array") {
return fill_static_inline_array(form, rest, env);
} else {
@ -684,7 +684,8 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env
void Compiler::fill_static_array_inline(const goos::Object& form,
const TypeSpec& content_type,
const std::vector<goos::Object>& args,
goos::Object* args_array,
int args_array_length,
StaticStructure* structure,
int offset,
Env* env) {
@ -692,10 +693,9 @@ void Compiler::fill_static_array_inline(const goos::Object& form,
auto deref_info = m_ts.get_deref_info(pointer_type);
assert(deref_info.can_deref);
assert(deref_info.mem_deref);
for (size_t i = 4; i < args.size(); i++) {
int arg_idx = i - 4;
for (int arg_idx = 0; arg_idx < args_array_length; arg_idx++) {
int elt_offset = offset + arg_idx * deref_info.stride;
auto sr = compile_static(args.at(i), env);
auto sr = compile_static(args_array[arg_idx], env);
if (is_integer(content_type)) {
typecheck(form, TypeSpec("integer"), sr.typespec());
} else {
@ -723,7 +723,6 @@ void Compiler::fill_static_array_inline(const goos::Object& form,
StaticResult Compiler::fill_static_array(const goos::Object& form,
const goos::Object& rest,
bool boxed,
Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
// (new 'static 'boxed-array ...)
@ -746,35 +745,98 @@ StaticResult Compiler::fill_static_array(const goos::Object& form,
auto array_data_size_bytes = length * deref_info.stride;
// todo, segments
std::unique_ptr<StaticStructure> obj;
if (boxed) {
obj = std::make_unique<StaticBasic>(MAIN_SEGMENT, "array");
} else {
obj = std::make_unique<StaticStructure>(MAIN_SEGMENT);
}
int array_header_size = boxed ? 16 : 0;
obj->data.resize(array_header_size + array_data_size_bytes);
obj = std::make_unique<StaticStructure>(MAIN_SEGMENT);
if (boxed) {
// 0 - 4 : type tag (set automatically)
// 4 - 8 : length
memcpy(obj->data.data() + 4, &length, 4);
// 8 - 12 allocated length
memcpy(obj->data.data() + 8, &length, 4);
// 12 - 16 content type
auto runtime_type = m_ts.lookup_type(content_type.base_type())->get_runtime_name();
obj->add_type_record(runtime_type, 12);
}
obj->data.resize(array_data_size_bytes);
// now add arguments:
fill_static_array_inline(form, content_type, args, obj.get(), array_header_size, env);
fill_static_array_inline(form, content_type, args.data() + 4, args.size() - 4, obj.get(), 0, env);
TypeSpec result_type;
if (boxed) {
result_type = m_ts.make_array_typespec(content_type);
} else {
result_type = m_ts.make_pointer_typespec(content_type);
result_type = m_ts.make_pointer_typespec(content_type);
auto result = StaticResult::make_structure_reference(obj.get(), result_type);
fie->add_static(std::move(obj));
return result;
}
StaticResult Compiler::fill_static_boxed_array(const goos::Object& form,
const goos::Object& rest,
Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
// (new 'static 'boxed-array ...)
// get all arguments now
// auto args = get_list_as_vector(rest);
auto args = get_va(form, rest);
if (args.unnamed.size() < 2) {
throw_compiler_error(form, "new static boxed array must have type and min-size arguments");
}
if (!args.has_named("type")) {
throw_compiler_error(form, "boxed array must have type");
}
auto content_type = parse_typespec(args.get_named("type"));
if (!args.has_named("length")) {
throw_compiler_error(form, "boxed array must have length");
}
s64 length;
if (!try_getting_constant_integer(args.get_named("length"), &length, env)) {
throw_compiler_error(form, "boxed array has invalid length");
}
s64 allocated_length;
if (args.has_named("allocated-length")) {
if (!try_getting_constant_integer(args.get_named("allocated-length"), &allocated_length, env)) {
throw_compiler_error(form, "boxed array has invalid allocated-length");
}
} else {
allocated_length = length;
}
s64 initialized_count = args.unnamed.size() - 2;
if (initialized_count > length) {
throw_compiler_error(form, "Initialized {} elements, but length was {}", initialized_count,
length);
}
if (length > allocated_length) {
throw_compiler_error(form, "Length {} is longer than the allocated-length {}", length,
allocated_length);
}
// todo - generalize this array stuff if we ever need other types of static arrays.
auto pointer_type = m_ts.make_pointer_typespec(content_type);
auto deref_info = m_ts.get_deref_info(pointer_type);
assert(deref_info.can_deref);
assert(deref_info.mem_deref);
auto array_data_size_bytes = length * deref_info.stride;
// todo, segments
std::unique_ptr<StaticStructure> obj;
obj = std::make_unique<StaticBasic>(MAIN_SEGMENT, "array");
int array_header_size = 16;
obj->data.resize(array_header_size + array_data_size_bytes);
// 0 - 4 : type tag (set automatically)
// 4 - 8 : length
memcpy(obj->data.data() + 4, &length, 4);
// 8 - 12 allocated length
memcpy(obj->data.data() + 8, &allocated_length, 4);
// 12 - 16 content type
auto runtime_type = m_ts.lookup_type(content_type.base_type())->get_runtime_name();
obj->add_type_record(runtime_type, 12);
// now add arguments:
fill_static_array_inline(form, content_type, args.unnamed.data() + 2, args.unnamed.size() - 2,
obj.get(), array_header_size, env);
TypeSpec result_type;
result_type = m_ts.make_array_typespec(content_type);
auto result = StaticResult::make_structure_reference(obj.get(), result_type);
fie->add_static(std::move(obj));
return result;

View file

@ -36,8 +36,7 @@
(new
'static
'boxed-array
vif-disasm-element
34
:type vif-disasm-element :length 34 :allocated-length 34
(new 'static 'vif-disasm-element :mask #x7f :string1 "nop")
(new 'static 'vif-disasm-element
:mask #x7f

View file

@ -26,8 +26,7 @@
(new
'static
'boxed-array
uint8
32
:type uint8 :length 32 :allocated-length 32
#x2
#x5
#x2
@ -98,7 +97,3 @@
63
)
)

View file

@ -4,13 +4,17 @@
;; definition for symbol EulSafe, type (array int32)
(define
EulSafe
(the-as (array int32) (new 'static 'boxed-array int32 4 0 1 2 0))
(the-as (array int32)
(new 'static 'boxed-array :type int32 :length 4 :allocated-length 4 0 1 2 0)
)
)
;; definition for symbol EulNext, type (array int32)
(define
EulNext
(the-as (array int32) (new 'static 'boxed-array int32 4 1 2 0 1))
(the-as (array int32)
(new 'static 'boxed-array :type int32 :length 4 :allocated-length 4 1 2 0 1)
)
)
;; definition of type euler-angles
@ -37,7 +41,3 @@
;; failed to figure out what this is:
(let ((v0-1 0))
)

View file

@ -92,8 +92,7 @@
(new
'static
'boxed-array
float
32
:type float :length 32 :allocated-length 32
1.0
0.5
0.25
@ -137,8 +136,7 @@
(new
'static
'boxed-array
float
32
:type float :length 32 :allocated-length 32
0.7853982
0.4636476
0.24497867

View file

@ -35,7 +35,19 @@
(define
*title-credits-scale*
(the-as (array float)
(new 'static 'boxed-array float 8 0.9 0.9 0.6 0.6 1.0 0.9 1.1 0.9)
(new
'static
'boxed-array
:type float :length 8 :allocated-length 8
0.9
0.9
0.6
0.6
1.0
0.9
1.1
0.9
)
)
)
@ -43,7 +55,19 @@
(define
*title-credits-spacing*
(the-as (array int32)
(new 'static 'boxed-array int32 8 15 20 15 15 20 15 20 15)
(new
'static
'boxed-array
:type int32 :length 8 :allocated-length 8
15
20
15
15
20
15
20
15
)
)
)
@ -196,7 +220,3 @@
)
)
)

View file

@ -48,7 +48,14 @@
;; definition for symbol *text-group-names*, type (array string)
(define
*text-group-names*
(the-as (array string) (new 'static 'boxed-array string 1 "common"))
(the-as (array string)
(new
'static
'boxed-array
:type string :length 1 :allocated-length 1
"common"
)
)
)
;; definition for symbol *common-text-heap*, type kheap

View file

@ -210,7 +210,12 @@ TEST_F(DataDecompTest, VifDisasmArray) {
auto decomp =
decompile_at_label_guess_type(parsed.label("L148"), parsed.labels, {parsed.words}, dts->ts);
check_forms_equal(decomp.print(),
"(new 'static 'boxed-array vif-disasm-element 3\n"
"(new 'static 'boxed-array :type\n"
" vif-disasm-element\n"
" :length\n"
" 3\n"
" :allocated-length\n"
" 3\n"
" (new 'static 'vif-disasm-element :mask #x7f :string1 \"nop\")\n"
" (new 'static 'vif-disasm-element :mask #x7f :tag (vif-cmd-32 stcycl) :print "
"#x2 :string1 \"stcycl\")\n"

View file

@ -21,11 +21,11 @@
(format #t "int: ~d~%" obj)
obj)
(let ((test-arr (new 'static 'boxed-array test-bitfield 12)))
(let ((test-arr (new 'static 'boxed-array :type test-bitfield :length 12)))
(format #t "content type: ~A~%" (-> test-arr content-type))
)
(let ((test-arr (new 'static 'boxed-array test-enum 12)))
(let ((test-arr (new 'static 'boxed-array :type test-enum :length 12)))
(format #t "content type: ~A~%" (-> test-arr content-type))
)

View file

@ -1,4 +1,4 @@
(let ((arr (new 'static 'boxed-array object 12 32 'asdf "test" '( a b ))))
(let ((arr (new 'static 'boxed-array :type object :length 12 32 'asdf "test" '( a b ))))
(dotimes (i 5)
(format #t "~A " (-> arr i))
)