Merge pull request #97 from water111/w/add-types-to-all-types

Add some types
This commit is contained in:
water111 2020-10-25 18:08:11 -04:00 committed by GitHub
commit fd8a0a5cf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 29371 additions and 210 deletions

View file

@ -300,6 +300,14 @@ class Object {
return float_obj.value;
}
const FloatType& as_float() const {
if (type != ObjectType::FLOAT) {
throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " +
print());
}
return float_obj.value;
}
char& as_char() {
if (type != ObjectType::CHAR) {
throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " +

View file

@ -239,7 +239,13 @@ StructureDefResult parse_structure_def(StructureType* type,
result.generate_runtime_type = false;
} else if (opt_name == ":pack-me") {
result.pack_me = true;
} else {
} else if (opt_name == ":heap-base") {
u16 hb = get_int(car(rest));
rest = cdr(rest);
flags.heap_base = hb;
}
else {
throw std::runtime_error("Invalid option in field specification: " + opt_name);
}
}

View file

@ -312,10 +312,13 @@ bool get_ptr_offset(IR* ir, Register dst, Register base, int* result) {
get_ptr_offset_zero(as_math, base, result);
}
bool is_weird(Function& function, LinkedObjectFile& file, TypeInspectorResult* result) {
int get_start_idx(Function& function,
LinkedObjectFile& file,
TypeInspectorResult* result,
const std::string& parent_type) {
if (function.basic_blocks.size() > 1) {
result->warnings += " too many basic blocks";
return true;
return 0;
}
/*
@ -341,64 +344,94 @@ bool is_weird(Function& function, LinkedObjectFile& file, TypeInspectorResult* r
// check size
if (function.basic_ops.size() < 7) {
result->warnings += " not enough basic ops";
return true;
return 0;
}
auto& move_op = function.basic_ops.at(0);
if (!is_reg_reg_move(move_op.get(), make_gpr(Reg::GP), make_gpr(Reg::A0))) {
result->warnings += "bad first move";
return true;
return 0;
}
auto& get_format_op = function.basic_ops.at(1);
if (!is_get_sym_value(get_format_op.get(), make_gpr(Reg::T9), "format")) {
result->warnings += "bad get format";
return true;
if (is_get_sym_value(get_format_op.get(), make_gpr(Reg::T9), "format")) {
auto& get_true = function.basic_ops.at(2);
if (!is_get_sym(get_true.get(), make_gpr(Reg::A0), "#t")) {
result->warnings += "bad get true";
return 0;
}
auto& get_str = function.basic_ops.at(3);
if (!is_get_label(get_str.get(), make_gpr(Reg::A1))) {
result->warnings += "bad get label";
return 0;
}
auto str = file.get_goal_string_by_label(file.labels.at(get_label_id_of_set(get_str.get())));
if (str != "[~8x] ~A~%") {
result->warnings += "bad type dec string: " + str;
return 0;
}
auto& move2_op = function.basic_ops.at(4);
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP))) {
result->warnings += "bad second move";
return 0;
}
auto& load_op = function.basic_ops.at(5);
bool is_basic_load = is_get_load_with_offset(load_op.get(), make_gpr(Reg::A3),
IR_Load::UNSIGNED, 4, make_gpr(Reg::GP), -4);
result->is_basic = is_basic_load;
bool is_struct_load = is_get_sym(load_op.get(), make_gpr(Reg::A3), function.method_of_type);
if (!is_basic_load && !is_struct_load) {
result->warnings += "bad load";
return 0;
}
auto& call = function.basic_ops.at(6);
if (!dynamic_cast<IR_Call*>(call.get())) {
result->warnings += "bad call";
return 0;
}
// okay!
return 7;
} else {
if (is_get_sym_value(get_format_op.get(), make_gpr(Reg::V1), parent_type)) {
// now get the inspect method.
auto& get_method_op = function.basic_ops.at(2);
if (!is_get_load_with_offset(get_method_op.get(), make_gpr(Reg::T9), IR_Load::UNSIGNED, 4,
make_gpr(Reg::V1), 28)) {
result->warnings += "bad get method op " + get_method_op->print(file);
return 0;
}
auto& move2_op = function.basic_ops.at(3);
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A0), make_gpr(Reg::GP))) {
result->warnings += "bad move2 op " + move2_op->print(file);
return 0;
}
auto& call_op = function.basic_ops.at(4);
if (!dynamic_cast<IR_Call*>(call_op.get())) {
result->warnings += "bad call op " + call_op->print(file);
return 0;
}
result->warnings += "inherited inpspect of " + parent_type;
result->is_basic = true;
return 5;
} else {
result->warnings +=
"unrecognized get op: " + get_format_op->print(file) + " parent was " + parent_type;
return 0;
}
}
auto& get_true = function.basic_ops.at(2);
if (!is_get_sym(get_true.get(), make_gpr(Reg::A0), "#t")) {
result->warnings += "bad get true";
return true;
}
auto& get_str = function.basic_ops.at(3);
if (!is_get_label(get_str.get(), make_gpr(Reg::A1))) {
result->warnings += "bad get label";
return true;
}
auto str = file.get_goal_string_by_label(file.labels.at(get_label_id_of_set(get_str.get())));
if (str != "[~8x] ~A~%") {
result->warnings += "bad type dec string: " + str;
return true;
}
auto& move2_op = function.basic_ops.at(4);
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP))) {
result->warnings += "bad second move";
return true;
}
auto& load_op = function.basic_ops.at(5);
bool is_basic_load = is_get_load_with_offset(load_op.get(), make_gpr(Reg::A3), IR_Load::UNSIGNED,
4, make_gpr(Reg::GP), -4);
result->is_basic = is_basic_load;
bool is_struct_load = is_get_sym(load_op.get(), make_gpr(Reg::A3), function.method_of_type);
if (!is_basic_load && !is_struct_load) {
result->warnings += "bad load";
return true;
}
auto& call = function.basic_ops.at(6);
if (!dynamic_cast<IR_Call*>(call.get())) {
result->warnings += "bad call";
return true;
}
return false;
}
int identify_basic_field(int idx,
@ -706,11 +739,11 @@ TypeInspectorResult inspect_inspect_method(Function& inspect,
assert(flags.pad == 0);
auto& bad_set = get_config().bad_inspect_types;
if (is_weird(inspect, file, &result) || bad_set.find(type_name) != bad_set.end()) {
int idx = get_start_idx(inspect, file, &result, result.parent_type_name);
if (idx == 0 || bad_set.find(type_name) != bad_set.end()) {
// printf("was weird: %s\n", result.warnings.c_str());
return result;
}
int idx = 7;
while (idx < int(inspect.basic_ops.size()) - 1 && idx != -1) {
idx = detect(idx, inspect, file, &result);
}

File diff suppressed because it is too large Load diff

View file

@ -3,14 +3,14 @@
{
"game_version":1,
// the order here matters. KERNEL and GAME should go first
"dgo_names":["CGO/KERNEL.CGO","CGO/GAME.CGO"], /*
, "CGO/ENGINE.CGO"
"dgo_names":["CGO/KERNEL.CGO","CGO/GAME.CGO",
"CGO/ENGINE.CGO"
, "CGO/ART.CGO", "DGO/BEA.DGO", "DGO/CIT.DGO", "CGO/COMMON.CGO", "DGO/DAR.DGO", "DGO/DEM.DGO",
"DGO/FIN.DGO", "DGO/INT.DGO", "DGO/JUB.DGO", "DGO/JUN.DGO", "CGO/JUNGLE.CGO", "CGO/L1.CGO", "DGO/FIC.DGO",
"DGO/LAV.DGO", "DGO/MAI.DGO", "CGO/MAINCAVE.CGO", "DGO/MIS.DGO", "DGO/OGR.DGO", "CGO/RACERP.CGO", "DGO/ROB.DGO", "DGO/ROL.DGO",
"DGO/SNO.DGO", "DGO/SUB.DGO", "DGO/SUN.DGO", "CGO/SUNKEN.CGO", "DGO/SWA.DGO", "DGO/TIT.DGO", "DGO/TRA.DGO", "DGO/VI1.DGO",
"DGO/VI2.DGO", "DGO/VI3.DGO", "CGO/VILLAGEP.CGO", "CGO/WATER-AN.CGO"
],*/
],
"write_disassembly":true,
"write_hex_near_instructions":false,
@ -34,7 +34,8 @@
"types_with_bad_inspect_methods":[
"engine",
"bsp-header",
"joint-anim-matrix"
"joint-anim-matrix",
"part-tracker"
],
"asm_functions_by_name":[

View file

@ -58,6 +58,19 @@ void DecompilerTypeSystem::parse_type_defs(const std::vector<std::string>& file_
} else if (car(o).as_symbol()->name == "deftype") {
parse_deftype(cdr(o), &ts);
} else if (car(o).as_symbol()->name == "declare-type") {
auto* rest = &cdr(o);
auto type_name = car(*rest);
rest = &cdr(*rest);
auto type_kind = car(*rest);
if (!cdr(*rest).is_empty_list()) {
throw std::runtime_error("malformed declare-type");
}
if (type_kind.as_symbol()->name == "basic") {
ts.forward_declare_type_as_basic(type_name.as_symbol()->name);
} else {
throw std::runtime_error("bad declare-type");
}
} else {
throw std::runtime_error("Decompiler cannot parse " + car(o).print());
}

View file

@ -39,4 +39,8 @@
- The `&+` form now accepts more than two arguments.
- The `&+` form now works on `inline-array` and `structure`.
- In the case where the type system would use a result type of `lca(none, x)`, the result type is now `none` instead of compiler abort.
- The "none value" is now `(none)` instead of `none`
- The "none value" is now `(none)` instead of `none`
- Creating a field of 128-bit value type no longer causes a compiler crash
- 128-bit fields are inspected as `<cannot-print>`
- Static fields can now contain floating point values

View file

@ -5,3 +5,429 @@
;; name in dgo: vector-h
;; dgos: GAME, ENGINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; bit array
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(deftype bit-array (basic)
((length int32 :offset-assert 4)
(allocated-length int32 :offset-assert 8)
(_pad uint8)
)
:method-count-assert 13
:size-assert #xd
:flag-assert #xd0000000d
(:methods
(dummy-9 () none 9)
(dummy-10 () none 10)
(dummy-11 () none 11)
(dummy-12 () none 12)
)
)
;; todo new
;; todo 4
;; todo 5
;; todo 9
;; todo 10
;; todo 11
;; todo 12
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; vector types (integer)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Vector of 4 unsigned bytes.
(deftype vector4ub (structure)
((data uint8 4 :offset-assert 0)
(x uint8 :offset 0)
(y uint8 :offset 1)
(z uint8 :offset 2)
(w uint8 :offset 3)
(clr uint32 :offset 0)
)
:pack-me
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Vector of 4 signed bytes
(deftype vector4b (structure)
((data int8 4 :offset-assert 0)
(x int8 :offset 0)
(y int8 :offset 1)
(z int8 :offset 2)
(w int8 :offset 3)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Vector of 2 signed halfwords
(deftype vector2h (structure)
((data int16 2 :offset-assert 0)
(x int16 :offset 0)
(y int16 :offset 2)
)
:pack-me
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Vector of 2 unsigned halfwords
(deftype vector2uh (structure)
((data uint16 2 :offset-assert 0)
(x uint16 :offset 0)
(y uint16 :offset 2)
(val uint32 :offset 0)
)
:pack-me
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Vector of 3 halfwords
(deftype vector3h (structure)
((data int16 2 :offset-assert 0) ;; probably a bug, should be 3.
(x int16 :offset 0)
(y int16 :offset 2)
(z int16 :offset-assert 4)
)
:method-count-assert 9
:size-assert #x6
:flag-assert #x900000006
)
;; Vector of 2 signed words
(deftype vector2w (structure)
((data int32 2 :offset-assert 0)
(x int32 :offset 0)
(y int32 :offset 4)
)
:pack-me
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
;; Vector of 3 signed words
(deftype vector3w (structure)
((data int32 3 :offset-assert 0)
(x int32 :offset 0)
(y int32 :offset 4)
(z int32 :offset 8)
)
:method-count-assert 9
:size-assert #xc
:flag-assert #x90000000c
)
;; Vector of 4 signed words
(deftype vector4w (structure)
((data int32 4 :offset-assert 0)
(x int32 :offset 0)
(y int32 :offset 4)
(z int32 :offset 8)
(w int32 :offset 12)
(dword uint64 2 :offset 0)
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(defmethod print vector4w ((this vector4w))
(format #t "#<vector4w ~D ~D ~D ~D @ #x~X>"
(-> this data 0)
(-> this data 1)
(-> this data 2)
(-> this data 3)
this)
this
)
;; Two vector4w's
(deftype vector4w-2 (structure)
((data int32 8 :offset-assert 0)
(quad uint128 2 :offset 0)
(vector vector4w 2 :offset 0)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
;; Three vector4w's
(deftype vector4w-3 (structure)
((data int32 12 :offset-assert 0)
(quad uint128 3 :offset 0)
(vector vector4w 3 :offset 0)
)
:method-count-assert 9
:size-assert #x30
:flag-assert #x900000030
)
;; Four vector4w's
(deftype vector4w-4 (structure)
((data int32 16 :offset-assert 0)
(quad uint128 4 :offset 0)
(vector vector4w 4 :offset 0)
)
:method-count-assert 9
:size-assert #x40
:flag-assert #x900000040
)
;; Vector of 4 halfwords
(deftype vector4h (structure)
((data int16 4 :offset-assert 0)
(x int16 :offset 0)
(y int16 :offset 2)
(z int16 :offset 4)
(w int16 :offset 6)
(long uint64 :offset 0)
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
;; Vector of 8 halfwords
(deftype vector8h (structure)
((data int16 8 :offset-assert 0)
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;; Vector of 16 signed bytes
(deftype vector16b (structure)
((data int8 8 :offset-assert 0)
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; vector types (floating point)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Vector of 4 floats. Shortened to "vector" because it is commonly used.
(deftype vector (structure)
((data float 4 :offset-assert 0)
(x float :offset 0)
(y float :offset 4)
(z float :offset 8)
(w float :offset 12)
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(defmethod inspect vector ((this vector))
(format #t "[~8x] vector~%" this)
(format #t "~T[~F] [~F] [~F] [~F]~%"
(-> this data 0)
(-> this data 1)
(-> this data 2)
(-> this data 3))
this)
(defmethod print vector ((this vector))
(format #t "#<vector ~F ~F ~F ~F @ #x~X>"
(-> this data 0)
(-> this data 1)
(-> this data 2)
(-> this data 3)
this)
this)
(define *null-vector* (new 'static 'vector :x 0. :y 0. :z 0. :w 1.))
(define *identity-vector* (new 'static 'vector :x 1. :y 1. :z 1. :w 1.))
(define *x-vector* (new 'static 'vector :x 1. :y 0. :z 0. :w 1.))
(define *y-vector* (new 'static 'vector :x 0. :y 1. :z 0. :w 1.))
(define *z-vector* (new 'static 'vector :x 0. :y 0. :z 1. :w 1.))
(define *up-vector* (new 'static 'vector :x 0. :y 1. :z 0. :w 1.))
;; Three vector's
(deftype vector4s-3 (structure)
((data float 12 :offset-assert 0) ;; guess
(quad uint128 3 :offset 0)
(vector vector4w 3 :offset 0) ;; guess
)
:method-count-assert 9
:size-assert #x30
:flag-assert #x900000030
)
(deftype vector-array (inline-array-class)
(
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(set! (-> vector-array heap-base) 16)
(deftype rgbaf (vector)
((r float :offset 0)
(g float :offset 4)
(b float :offset 8)
(a float :offset 12)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype plane (vector)
((a float :offset 0)
(b float :offset 4)
(c float :offset 8)
(d float :offset 12)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype sphere (vector)
((r float :offset 12)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
; (deftype isphere (vec4s)
; ()
; :method-count-assert 9
; :size-assert #x10
; :flag-assert #x900000010
; )
(deftype box8s (structure)
((data float 8 :offset-assert 0)
(quad uint128 2 :offset 0)
(vector vector 2 :offset 0)
(min vector :inline :offset 0)
(max vector :inline :offset 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype box8s-array (inline-array-class)
()
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(set! (-> box8s-array heap-base) 32)
(deftype cylinder (structure)
((origin vector :inline :offset-assert 0)
(axis vector :inline :offset-assert 16)
(radius float :offset-assert 32)
(length float :offset-assert 36)
)
:method-count-assert 11
:size-assert #x28
:flag-assert #xb00000028
(:methods
(dummy-9 () none 9)
(dummy-10 () none 10)
)
)
(deftype cylinder-flat (structure)
((origin vector :inline :offset-assert 0)
(axis vector :inline :offset-assert 16)
(radius float :offset-assert 32)
(length float :offset-assert 36)
)
:method-count-assert 11
:size-assert #x28
:flag-assert #xb00000028
(:methods
(dummy-9 () none 9)
(dummy-10 () none 10)
)
)
;; vector-h
(deftype vertical-planes (structure)
((data uint128 4 :offset-assert 0) ;; probably wrong
)
:method-count-assert 9
:size-assert #x40
:flag-assert #x900000040
)
(deftype vertical-planes-array (basic)
((length uint32 :offset-assert 4)
(data vertical-planes :dynamic :offset 16) ;; todo, why is this here?
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype qword (structure)
((data uint32 4 :offset-assert 0)
(byte uint8 16 :offset 0)
(hword uint16 8 :offset 0)
(word uint32 4 :offset 0)
(dword uint64 2 :offset 0)
(quad uint128 :offset 0)
(vector vector :inline :offset 0)
(vector4w vector4w :inline :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype vector3s (structure)
((data float 3 :offset-assert 0)
(x float :offset 0)
(y float :offset 4)
(z float :offset 8)
)
:method-count-assert 9
:size-assert #xc
:flag-assert #x90000000c
)
;; 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
; )
(define *zero-vector* (new 'static 'vector :x 0. :y 0. :z 0. :w 0.))

View file

@ -94,6 +94,7 @@ class Compiler {
const std::string& method_type_name = "");
bool try_getting_constant_integer(const goos::Object& in, int64_t* out, Env* env);
float try_getting_constant_float(const goos::Object& in, float* out, Env* env);
TypeSystem m_ts;
std::unique_ptr<GlobalEnv> m_global_env = nullptr;
@ -189,6 +190,7 @@ class Compiler {
// Math
Val* compile_add(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_sub(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_mul(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_div(const goos::Object& form, const goos::Object& rest, Env* env);

View file

@ -215,6 +215,17 @@ bool Compiler::try_getting_constant_integer(const goos::Object& in, int64_t* out
return true;
}
// todo, try more things like constants before giving up.
return false;
}
float Compiler::try_getting_constant_float(const goos::Object& in, float* out, Env* env) {
(void)env;
if (in.is_float()) {
*out = in.as_float();
return true;
}
// todo, try more things like constants before giving up.
return false;
}

View file

@ -119,6 +119,14 @@ Val* Compiler::compile_new_static_structure_or_basic(const goos::Object& form,
throw_compile_error(
form, "Setting a basic field to anything other than a symbol is currently unsupported");
}
} else if (is_float(field_info.type)) {
float value = 0.f;
if (!try_getting_constant_float(field_value, &value, env)) {
throw_compile_error(form, fmt::format("Field {} is a float, but the value given couldn't "
"be converted to a float at compile time.",
field_name_def));
}
memcpy(obj->data.data() + field_offset, &value, sizeof(float));
}
else {

View file

@ -111,24 +111,6 @@ void Compiler::generate_field_description(const goos::Object& form,
if (m_ts.typecheck(m_ts.make_typespec("type"), f.type(), "", false, false)) {
// type
return;
} else if (m_ts.typecheck(m_ts.make_typespec("basic"), f.type(), "", false, false) ||
m_ts.typecheck(m_ts.make_typespec("binteger"), f.type(), "", false, false) ||
m_ts.typecheck(m_ts.make_typespec("pair"), f.type(), "", false, false)) {
// basic, binteger, pair
str_template += fmt::format("~T{}: ~A~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("integer"), f.type(), "", false, false)) {
// Integer
str_template += fmt::format("~T{}: ~D~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("float"), f.type(), "", false, false)) {
// Float
str_template += fmt::format("~T{}: ~f~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("pointer"), f.type(), "", false, false)) {
// Pointers
str_template += fmt::format("~T{}: #x~X~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (f.is_array() && !f.is_dynamic()) {
// Arrays
str_template += fmt::format("~T{}[{}] @ #x~X~%", f.name(), f.array_size());
@ -141,6 +123,29 @@ void Compiler::generate_field_description(const goos::Object& form,
// Structure
str_template += fmt::format("~T{}: #<{} @ #x~X>~%", f.name(), f.type().print());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("basic"), f.type(), "", false, false) ||
m_ts.typecheck(m_ts.make_typespec("binteger"), f.type(), "", false, false) ||
m_ts.typecheck(m_ts.make_typespec("pair"), f.type(), "", false, false)) {
// basic, binteger, pair
str_template += fmt::format("~T{}: ~A~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("integer"), f.type(), "", false, false)) {
// Integer
if (f.type().print() == "uint128") {
str_template += fmt::format("~T{}: <cannot-print>~%", f.name());
} else {
str_template += fmt::format("~T{}: ~D~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
}
} else if (m_ts.typecheck(m_ts.make_typespec("float"), f.type(), "", false, false)) {
// Float
str_template += fmt::format("~T{}: ~f~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else if (m_ts.typecheck(m_ts.make_typespec("pointer"), f.type(), "", false, false)) {
// Pointers
str_template += fmt::format("~T{}: #x~X~%", f.name());
format_args.push_back(get_field_of_structure(type, reg, f.name(), env)->to_gpr(env));
} else {
// Otherwise, we havn't implemented it!
str_template += fmt::format("~T{}: Undefined!~%", f.name());