From e7f8620c92543150cecf6754aceb1df062b63d8e Mon Sep 17 00:00:00 2001 From: water Date: Sun, 13 Sep 2020 10:40:21 -0400 Subject: [PATCH] add floats and inline stuff --- goal_src/goal-lib.gc | 14 ++- goal_src/kernel-defs.gc | 148 ++++++++++++++++++++++++ goal_src/kernel/gcommon.gc | 17 +++ goal_src/test/test-declare-inline.gc | 7 ++ goal_src/test/test-floating-point-1.gc | 1 + goal_src/test/test-inline-call.gc | 7 ++ goal_src/test/test-string-symbol.gc | 1 + goalc/compiler/Compiler.cpp | 2 +- goalc/compiler/Compiler.h | 4 + goalc/compiler/Env.h | 9 +- goalc/compiler/IR.cpp | 45 ++++++- goalc/compiler/IR.h | 15 +++ goalc/compiler/StaticObject.cpp | 32 +++++ goalc/compiler/StaticObject.h | 11 ++ goalc/compiler/Val.cpp | 11 +- goalc/compiler/Val.h | 6 +- goalc/compiler/compilation/Atoms.cpp | 24 +++- goalc/compiler/compilation/Function.cpp | 48 +++++++- goalc/compiler/compilation/Math.cpp | 3 + test/test_compiler_and_runtime.cpp | 50 ++++++++ 20 files changed, 434 insertions(+), 21 deletions(-) create mode 100644 goal_src/kernel-defs.gc create mode 100644 goal_src/test/test-declare-inline.gc create mode 100644 goal_src/test/test-floating-point-1.gc create mode 100644 goal_src/test/test-inline-call.gc create mode 100644 goal_src/test/test-string-symbol.gc diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index 2c746a53f..77ae4e31f 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -1,3 +1,13 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; OTHER STUFF +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; get list of all goal files +(asm-file "goal_src/build/all_files.gc") + +;; tell compiler about stuff defined/implemented in the runtime. +(asm-file "goal_src/kernel-defs.gc") + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; BUILD SYSTEM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -23,13 +33,11 @@ ) ) -;; load list of all goal files -(asm-file "goal_src/build/all_files.gc") - (defmacro e () `(:exit) ) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CONDITIONAL COMPILATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/goal_src/kernel-defs.gc b/goal_src/kernel-defs.gc new file mode 100644 index 000000000..3c97a5608 --- /dev/null +++ b/goal_src/kernel-defs.gc @@ -0,0 +1,148 @@ +;; kernel-defs.gc +;; everything defined in the C Kernel / runtime + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; kscheme - InitHeapAndSymbol +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; fixed symbols +(define-extern #f symbol) +(define-extern #t symbol) +(define-extern function type) +(define-extern basic type) +(define-extern string type) +(define-extern symbol type) +(define-extern type type) +(define-extern object type) +(define-extern link-block type) +(define-extern integer type) +(define-extern sinteger type) +(define-extern uinteger type) +(define-extern binteger type) +(define-extern int8 type) +(define-extern int16 type) +(define-extern int32 type) +(define-extern int64 type) +(define-extern int128 type) +(define-extern uint8 type) +(define-extern uint16 type) +(define-extern uint32 type) +(define-extern uint64 type) +(define-extern uint128 type) +(define-extern float type) +(define-extern process-tree type) +(define-extern process type) +(define-extern thread type) +(define-extern structure type) +(define-extern pair type) +(define-extern pointer type) +(define-extern number type) +(define-extern array type) +(define-extern vu-function type) +(define-extern connectable type) +(define-extern stack-frame type) +(define-extern file-stream type) +(define-extern kheap type) +(define-extern nothing (function none)) +(define-extern delete-basic (function basic none)) +(define-extern static symbol) +(define-extern global kheap) +(define-extern debug kheap) +(define-extern loading-level kheap) ;; not a kheap at boot +(define-extern loading-package kheap) ;; not a kheap at boot +(define-extern process-level-heap kheap) ;; not a kheap at boot +(define-extern stack symbol) +(define-extern scratch symbol) +(define-extern *stratch-top* pointer) +(define-extern zero-func (function int)) +;; asize-of-basic-func - has a bug +;; copy-basic-func - has a bug +;; level - unknown type +;; art-group +;; texture-page-dir +;; texture-page +;; sound +;; dgo +;; top-level + +(define-extern string->symbol (function string symbol)) +(define-extern print (function object object)) +(define-extern inspect (function object object)) +(define-extern load (function string kheap object)) +(define-extern loado (function string kheap object)) +(define-extern unload (function string none)) +(define-extern _format function) +(define-extern malloc (function kheap int pointer)) +(define-extern kmalloc (function kheap int int string)) +(define-extern new-dynamic-structure (function kheap type int structure)) +(define-extern method-set! (function type int function none)) ;; may actually return function. +(define-extern link (function pointer string int kheap int pointer)) +(define-extern dgo-load (function string kheap int int)) +(define-extern link-begin (function pointer string int kheap int int)) +(define-extern link-resume (function int)) +;; mc-run +;; mc-format +;; mc-unformat +;; mc-create-file +;; mc-save +;; mc-load +;; mc-check-result +;; mc-get-slot-info +;; mc-makefile +;; kset-language + +(define-extern *debug-segment* symbol) +(define-extern *enable-method-set* int) +;; *boot-video-mode* ? +(define-extern *deci-count* int) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; klisten - InitListener +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; *listener-link-block* +;; *listener-function* +;; kernel-dispatcher +;; kernel-packages +;; *print-column* + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; kmachine - InitMachineScheme +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; put-display-env +;; syncv +;; sync-path +;; reset-path +;; rest-graph +;; dma-sync +;; gs-put-imr +;; gs-get-imr +;; gs-store-image +;; flush-cache +;; cpad-open +;; cpad-get-data +;; install-handler +;; install-debug-handler +;; file-stream-open +;; file-stream-close +;; file-stream-length +;; file-stream-seek +;; file-stream-read +;; file-stream-write +;; scf-get-language +;; scf-get-time +;; scf-get-aspect +;; scf-get-volume +;; scf-get-territory +;; scf-get-timeout +;; scf-get-inactive-timeout +;; dma-to-iop +;; kernel-shutdown +;; aybabtu +;; *stack-top* +;; *stack-base* +;; *stack-size* +;; *kernel-boot-message* +;; *kernel-boot-mode* +;; *kernel-boot-level* \ No newline at end of file diff --git a/goal_src/kernel/gcommon.gc b/goal_src/kernel/gcommon.gc index 0f99919f9..057dfb5d3 100644 --- a/goal_src/kernel/gcommon.gc +++ b/goal_src/kernel/gcommon.gc @@ -5,3 +5,20 @@ ;; name in dgo: gcommon ;; dgos: KERNEL +;; gcommon is the first file compiled and loaded. +;; it's expected that this function will mostly be hand-decompiled + + + +;; The "identity" returns its input unchanged. It uses the special GOAL "object" +;; type, which can basically be anything, so this will work on integers, floats, +;; strings, structures, arrays, etc. The only things which doesn't work with "object" +;; is a 128-bit integer. The upper 64-bits of the integer will usually be lost. +(defun identity ((x object)) + ;; there is an optional "docstring" that can go at the beginning of a function + "Function which returns its input. The first function of the game!" + + ;; the last thing in the function body is the return value. + x + ) + diff --git a/goal_src/test/test-declare-inline.gc b/goal_src/test/test-declare-inline.gc new file mode 100644 index 000000000..1ca61f64e --- /dev/null +++ b/goal_src/test/test-declare-inline.gc @@ -0,0 +1,7 @@ +(defun inline-test-function-1 ((x int)) + ;; inline this function by default. + (declare (inline)) + (* 4 x) + ) + +(inline-test-function-1 8) \ No newline at end of file diff --git a/goal_src/test/test-floating-point-1.gc b/goal_src/test/test-floating-point-1.gc new file mode 100644 index 000000000..96660318c --- /dev/null +++ b/goal_src/test/test-floating-point-1.gc @@ -0,0 +1 @@ +1.234 \ No newline at end of file diff --git a/goal_src/test/test-inline-call.gc b/goal_src/test/test-inline-call.gc new file mode 100644 index 000000000..bc69c9f11 --- /dev/null +++ b/goal_src/test/test-inline-call.gc @@ -0,0 +1,7 @@ +(defun inline-test-function-2 ((x integer)) + ;; inline this function by default. + (declare (allow-inline)) + (* 4 x) + ) + +(+ (inline-test-function-2 8) ((inline inline-test-function-2) 3)) \ No newline at end of file diff --git a/goal_src/test/test-string-symbol.gc b/goal_src/test/test-string-symbol.gc new file mode 100644 index 000000000..a4dd8b68f --- /dev/null +++ b/goal_src/test/test-string-symbol.gc @@ -0,0 +1 @@ +(print (string->symbol "test-string")) \ No newline at end of file diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index f50a2826a..6ca06f87a 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -206,7 +206,7 @@ std::vector Compiler::run_test(const std::string& source_code) { std::vector Compiler::run_test_no_load(const std::string& source_code) { auto code = m_goos.reader.read_from_file({source_code}); - auto compiled = compile_object_file("test-code", code, true); + compile_object_file("test-code", code, true); return {}; } diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index af93e5325..d77bd0df3 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -15,6 +15,7 @@ class Compiler { Compiler(); ~Compiler(); void execute_repl(); + goos::Interpreter& get_goos() { return m_goos; } FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit); std::unique_ptr compile_top_level_function(const std::string& name, const goos::Object& code, @@ -40,6 +41,8 @@ class Compiler { Val* compile_pair(const goos::Object& code, Env* env); Val* compile_integer(const goos::Object& code, Env* env); Val* compile_integer(s64 value, Env* env); + Val* compile_float(const goos::Object& code, Env* env); + Val* compile_float(float value, Env* env, int seg); Val* compile_symbol(const goos::Object& form, Env* env); Val* compile_string(const goos::Object& form, Env* env); Val* compile_string(const std::string& str, Env* env, int seg = MAIN_SEGMENT); @@ -137,6 +140,7 @@ class Compiler { // Function Val* compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_inline(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_declare(const goos::Object& form, const goos::Object& rest, Env* env); }; #endif // JAK_COMPILER_H diff --git a/goalc/compiler/Env.h b/goalc/compiler/Env.h index 026e6a879..a9fc91c03 100644 --- a/goalc/compiler/Env.h +++ b/goalc/compiler/Env.h @@ -90,6 +90,10 @@ class FileEnv : public Env { void debug_print_tl(); const std::vector>& functions() { return m_functions; } const std::vector>& statics() { return m_statics; } + const FunctionEnv& top_level_function() { + assert(m_top_level_func); + return *m_top_level_func; + } bool is_empty(); ~FileEnv() = default; @@ -137,7 +141,7 @@ class FunctionEnv : public DeclareEnv { void emit(std::unique_ptr ir) override; void finish(); RegVal* make_ireg(TypeSpec ts, emitter::RegKind kind) override; - const std::vector>& code() { return m_code; } + const std::vector>& code() const { return m_code; } int max_vars() const { return m_iregs.size(); } const std::vector& constraints() { return m_constraints; } void constrain(const IRegConstraint& c) { m_constraints.push_back(c); } @@ -167,7 +171,7 @@ class FunctionEnv : public DeclareEnv { int segment = -1; std::string method_of_type_name = "#f"; - + bool is_asm_func = false; std::vector unresolved_gotos; std::unordered_map params; @@ -181,7 +185,6 @@ class FunctionEnv : public DeclareEnv { std::vector m_constraints; // todo, unresolved gotos AllocationResult m_regalloc_result; - bool m_is_asm_func = false; bool m_aligned_stack_required = false; diff --git a/goalc/compiler/IR.cpp b/goalc/compiler/IR.cpp index 5c8ccb814..3174425e2 100644 --- a/goalc/compiler/IR.cpp +++ b/goalc/compiler/IR.cpp @@ -194,8 +194,12 @@ void IR_RegSet::do_codegen(emitter::ObjectGenerator* gen, if (val_reg == dest_reg) { gen->add_instr(IGen::null(), irec); - } else { + } else if (val_reg.is_gpr() && dest_reg.is_gpr()) { gen->add_instr(IGen::mov_gpr64_gpr64(dest_reg, val_reg), irec); + } else if (val_reg.is_xmm() && dest_reg.is_gpr()) { + gen->add_instr(IGen::movd_gpr32_xmm32(dest_reg, val_reg), irec); + } else { + assert(false); } } @@ -329,7 +333,7 @@ void IR_StaticVarAddr::do_codegen(emitter::ObjectGenerator* gen, ///////////////////// // FunctionAddr -/////////////////// +///////////////////// IR_FunctionAddr::IR_FunctionAddr(const RegVal* dest, FunctionEnv* src) : m_dest(dest), m_src(src) {} @@ -354,7 +358,7 @@ void IR_FunctionAddr::do_codegen(emitter::ObjectGenerator* gen, ///////////////////// // IntegerMath -/////////////////// +///////////////////// IR_IntegerMath::IR_IntegerMath(IntegerMathKind kind, RegVal* dest, RegVal* arg) : m_kind(kind), m_dest(dest), m_arg(arg) {} @@ -402,4 +406,39 @@ void IR_IntegerMath::do_codegen(emitter::ObjectGenerator* gen, default: assert(false); } +} + +///////////////////// +// StaticVarLoad +///////////////////// + +IR_StaticVarLoad::IR_StaticVarLoad(const RegVal* dest, const StaticObject* src) + : m_dest(dest), m_src(src) {} + +std::string IR_StaticVarLoad::print() { + return fmt::format("mov-svl {}, [{}]", m_dest->print(), m_src->print()); +} + +RegAllocInstr IR_StaticVarLoad::to_rai() { + RegAllocInstr rai; + rai.write.push_back(m_dest->ireg()); + return rai; +} + +void IR_StaticVarLoad::do_codegen(emitter::ObjectGenerator* gen, + const AllocationResult& allocs, + emitter::IR_Record irec) { + auto load_info = m_src->get_load_info(); + assert(m_src->get_addr_offset() == 0); + + if (m_dest->ireg().kind == emitter::RegKind::XMM) { + assert(load_info.load_signed == false); + assert(load_info.load_size == 4); + assert(load_info.requires_load == true); + + auto instr = gen->add_instr(IGen::static_load_xmm32(get_reg(m_dest, allocs, irec), 0), irec); + gen->link_instruction_static(instr, m_src->rec, 0); + } else { + assert(false); + } } \ No newline at end of file diff --git a/goalc/compiler/IR.h b/goalc/compiler/IR.h index 0443eb427..635005e39 100644 --- a/goalc/compiler/IR.h +++ b/goalc/compiler/IR.h @@ -159,6 +159,20 @@ class IR_StaticVarAddr : public IR { const StaticObject* m_src = nullptr; }; +class IR_StaticVarLoad : public IR { + public: + IR_StaticVarLoad(const RegVal* dest, const StaticObject* src); + std::string print() override; + RegAllocInstr to_rai() override; + void do_codegen(emitter::ObjectGenerator* gen, + const AllocationResult& allocs, + emitter::IR_Record irec) override; + + protected: + const RegVal* m_dest = nullptr; + const StaticObject* m_src = nullptr; +}; + class IR_FunctionAddr : public IR { public: IR_FunctionAddr(const RegVal* dest, FunctionEnv* src); @@ -199,6 +213,7 @@ class IR_IntegerMath : public IR { void do_codegen(emitter::ObjectGenerator* gen, const AllocationResult& allocs, emitter::IR_Record irec) override; + IntegerMathKind get_kind() const { return m_kind; } protected: IntegerMathKind m_kind; diff --git a/goalc/compiler/StaticObject.cpp b/goalc/compiler/StaticObject.cpp index 19dc920c6..dd0ef92ad 100644 --- a/goalc/compiler/StaticObject.cpp +++ b/goalc/compiler/StaticObject.cpp @@ -13,6 +13,9 @@ uint32_t push_data_to_byte_vector(T data, std::vector& v) { } } // namespace +//////////////// +// StaticString +//////////////// StaticString::StaticString(std::string data, int _seg) : text(std::move(data)), seg(_seg) {} std::string StaticString::print() const { @@ -48,4 +51,33 @@ void StaticString::generate(emitter::ObjectGenerator* gen) { int StaticString::get_addr_offset() const { return BASIC_OFFSET; +} + +//////////////// +// StaticFloat +//////////////// + +StaticFloat::StaticFloat(float _value, int _seg) : value(_value), seg(_seg) {} + +StaticObject::LoadInfo StaticFloat::get_load_info() const { + LoadInfo info; + info.requires_load = true; + info.load_size = 4; + info.load_signed = false; + info.prefer_xmm = true; + return info; +} + +void StaticFloat::generate(emitter::ObjectGenerator* gen) { + rec = gen->add_static_to_seg(seg, 4); + auto& d = gen->get_static_data(rec); + push_data_to_byte_vector(value, d); +} + +int StaticFloat::get_addr_offset() const { + return 0; +} + +std::string StaticFloat::print() const { + return fmt::format("(sf {})", value); } \ No newline at end of file diff --git a/goalc/compiler/StaticObject.h b/goalc/compiler/StaticObject.h index 34dc05b28..4b116b6cb 100644 --- a/goalc/compiler/StaticObject.h +++ b/goalc/compiler/StaticObject.h @@ -33,4 +33,15 @@ class StaticString : public StaticObject { int get_addr_offset() const override; }; +class StaticFloat : public StaticObject { + public: + explicit StaticFloat(float _value, int _seg); + float value = 0; + int seg = -1; + std::string print() const override; + LoadInfo get_load_info() const override; + void generate(emitter::ObjectGenerator* gen) override; + int get_addr_offset() const override; +}; + #endif // JAK_STATICOBJECT_H diff --git a/goalc/compiler/Val.cpp b/goalc/compiler/Val.cpp index f1de3f0e1..889cf1cc2 100644 --- a/goalc/compiler/Val.cpp +++ b/goalc/compiler/Val.cpp @@ -6,11 +6,14 @@ * Fallback to_gpr if a more optimized one is not provided. */ RegVal* Val::to_gpr(Env* fe) { + // TODO - handle 128-bit stuff here! auto rv = to_reg(fe); if (rv->ireg().kind == emitter::RegKind::GPR) { return rv; } else { - throw std::runtime_error("Val::to_gpr NYI"); // todo + auto re = fe->make_gpr(m_ts); + fe->emit(std::make_unique(re, rv)); + return re; } } @@ -74,4 +77,10 @@ RegVal* LambdaVal::to_reg(Env* fe) { assert(func); fe->emit(std::make_unique(re, func)); return re; +} + +RegVal* FloatConstantVal::to_reg(Env* fe) { + auto re = fe->make_xmm(m_ts); + fe->emit(std::make_unique(re, m_value)); + return re; } \ No newline at end of file diff --git a/goalc/compiler/Val.h b/goalc/compiler/Val.h index 239ee59fe..66190abc6 100644 --- a/goalc/compiler/Val.h +++ b/goalc/compiler/Val.h @@ -141,12 +141,12 @@ class IntegerConstantVal : public Val { class FloatConstantVal : public Val { public: - FloatConstantVal(TypeSpec ts, float value) : Val(std::move(ts)), m_value(value) {} - std::string print() const override { return "float-constant-" + std::to_string(m_value); } + FloatConstantVal(TypeSpec ts, StaticFloat* value) : Val(std::move(ts)), m_value(value) {} + std::string print() const override { return "float-constant-" + m_value->print(); } RegVal* to_reg(Env* fe) override; protected: - float m_value = -1.f; + StaticFloat* m_value = nullptr; }; // IntegerConstant // FloatConstant diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index e1ade2fb5..bfc4cc7ef 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -68,7 +68,8 @@ static const std::unordered_map< // // // LAMBDA {"lambda", &Compiler::compile_lambda}, - // {"inline", &Compiler::compile_inline}, + {"declare", &Compiler::compile_declare}, + {"inline", &Compiler::compile_inline}, // {"with-inline", &Compiler::compile_with_inline}, // {"rlet", &Compiler::compile_rlet}, // {"mlet", &Compiler::compile_mlet}, @@ -81,11 +82,6 @@ static const std::unordered_map< {"quote", &Compiler::compile_quote}, // {"defconstant", &Compiler::compile_defconstant}, // - // {"declare", &Compiler::compile_declare}, - // - // - // - // // // OBJECT // // {"the", &Compiler::compile_the}, @@ -150,6 +146,8 @@ Val* Compiler::compile(const goos::Object& code, Env* env) { return compile_symbol(code, env); case goos::ObjectType::STRING: return compile_string(code, env); + case goos::ObjectType::FLOAT: + return compile_float(code, env); default: ice("Don't know how to compile " + code.print()); } @@ -255,4 +253,18 @@ Val* Compiler::compile_string(const std::string& str, Env* env, int seg) { auto fie = get_parent_env_of_type(env); fie->add_static(std::move(obj)); return result; +} + +Val* Compiler::compile_float(const goos::Object& code, Env* env) { + assert(code.is_float()); + return compile_float(code.float_obj.value, env, MAIN_SEGMENT); +} + +Val* Compiler::compile_float(float value, Env* env, int seg) { + auto obj = std::make_unique(value, seg); + auto fe = get_parent_env_of_type(env); + auto result = fe->alloc_val(m_ts.make_typespec("float"), obj.get()); + auto fie = get_parent_env_of_type(env); + fie->add_static(std::move(obj)); + return result; } \ No newline at end of file diff --git a/goalc/compiler/compilation/Function.cpp b/goalc/compiler/compilation/Function.cpp index 48f33ef19..5a92dcf90 100644 --- a/goalc/compiler/compilation/Function.cpp +++ b/goalc/compiler/compilation/Function.cpp @@ -282,6 +282,7 @@ Val* Compiler::compile_function_or_method_call(const goos::Object& form, Env* en if (eval_args.empty()) { throw_compile_error(form, "0 argument method call is impossible to figure out"); } + printf("BAD %s\n", uneval_head.print().c_str()); assert(false); // nyi // head = compile_get_method_of_object(eval_args.front(), symbol_string(uneval_head), env); } @@ -359,4 +360,49 @@ Val* Compiler::compile_real_function_call(const goos::Object& form, } else { return return_reg; } -} \ No newline at end of file +} + +Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& rest, Env* env) { + auto& settings = get_parent_env_of_type(env)->settings; + + if (settings.is_set) { + throw_compile_error(form, "function has multiple declares"); + } + settings.is_set = true; + + for_each_in_list(rest, [&](const goos::Object& o) { + if (!o.is_pair()) { + throw_compile_error(o, "invalid declare specification"); + } + + auto first = o.as_pair()->car; + auto rrest = o.as_pair()->cdr; + + if (!first.is_symbol()) { + throw_compile_error(first, "invalid declare specification, expected a symbol"); + } + + if (first.as_symbol()->name == "inline") { + if (!rrest.is_empty_list()) { + throw_compile_error(first, "invalid inline declare"); + } + settings.allow_inline = true; + settings.inline_by_default = true; + settings.save_code = true; + } else if (first.as_symbol()->name == "allow-inline") { + if (!rrest.is_empty_list()) { + throw_compile_error(first, "invalid allow-inline declare"); + } + settings.allow_inline = true; + settings.inline_by_default = false; + settings.save_code = true; + } else if (first.as_symbol()->name == "asm-func") { + get_parent_env_of_type(env)->is_asm_func = true; + } + + else { + throw_compile_error(first, "unrecognized declare statement"); + } + }); + return get_none(); +} diff --git a/goalc/compiler/compilation/Math.cpp b/goalc/compiler/compilation/Math.cpp index 8a9f16689..d9bba8916 100644 --- a/goalc/compiler/compilation/Math.cpp +++ b/goalc/compiler/compilation/Math.cpp @@ -39,6 +39,7 @@ bool Compiler::is_singed_integer_or_binteger(const TypeSpec& ts) { } Val* Compiler::number_to_integer(Val* in, Env* env) { + (void)env; auto ts = in->type(); if (is_binteger(ts)) { assert(false); @@ -52,6 +53,7 @@ Val* Compiler::number_to_integer(Val* in, Env* env) { } Val* Compiler::number_to_binteger(Val* in, Env* env) { + (void)env; auto ts = in->type(); if (is_binteger(ts)) { return in; @@ -65,6 +67,7 @@ Val* Compiler::number_to_binteger(Val* in, Env* env) { } Val* Compiler::number_to_float(Val* in, Env* env) { + (void)env; auto ts = in->type(); if (is_binteger(ts)) { assert(false); diff --git a/test/test_compiler_and_runtime.cpp b/test/test_compiler_and_runtime.cpp index 0a731e948..882bad524 100644 --- a/test/test_compiler_and_runtime.cpp +++ b/test/test_compiler_and_runtime.cpp @@ -133,6 +133,48 @@ TEST(CompilerAndRuntime, BuildGame) { runtime_thread.join(); } +// TODO -move these into another file? +TEST(CompilerAndRuntime, InlineIsInline) { + Compiler compiler; + auto code = + compiler.get_goos().reader.read_from_file({"goal_src", "test", "test-declare-inline.gc"}); + auto compiled = compiler.compile_object_file("test-code", code, true); + EXPECT_EQ(compiled->functions().size(), 2); + auto& ir = compiled->top_level_function().code(); + bool got_mult = false; + for (auto& x : ir) { + EXPECT_EQ(dynamic_cast(x.get()), nullptr); + auto as_im = dynamic_cast(x.get()); + if (as_im) { + EXPECT_EQ(as_im->get_kind(), IntegerMathKind::IMUL_32); + got_mult = true; + } + } + EXPECT_TRUE(got_mult); +} + +TEST(CompilerAndRuntime, AllowInline) { + Compiler compiler; + auto code = + compiler.get_goos().reader.read_from_file({"goal_src", "test", "test-inline-call.gc"}); + auto compiled = compiler.compile_object_file("test-code", code, true); + EXPECT_EQ(compiled->functions().size(), 2); + auto& ir = compiled->top_level_function().code(); + int got_mult = 0; + int got_call = 0; + for (auto& x : ir) { + if (dynamic_cast(x.get())) { + got_call++; + } + auto as_im = dynamic_cast(x.get()); + if (as_im && as_im->get_kind() == IntegerMathKind::IMUL_32) { + got_mult++; + } + } + EXPECT_EQ(got_mult, 1); + EXPECT_EQ(got_call, 1); +} + TEST(CompilerAndRuntime, CompilerTests) { std::thread runtime_thread([]() { exec_runtime(0, nullptr); }); Compiler compiler; @@ -184,6 +226,14 @@ TEST(CompilerAndRuntime, CompilerTests) { runner.run_test("test-sub-2.gc", {"4\n"}); runner.run_test("test-mul-1.gc", {"-12\n"}); + expected = "test-string"; + runner.run_test("test-string-symbol.gc", {expected}, expected.size()); + runner.run_test("test-declare-inline.gc", {"32\n"}); + runner.run_test("test-inline-call.gc", {"44\n"}); + + // float + runner.run_test("test-floating-point-1.gc", {"1067316150\n"}); + compiler.shutdown_target(); runtime_thread.join(); runner.print_summary();