mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
add floats and inline stuff
This commit is contained in:
parent
90a7e9b4b9
commit
e7f8620c92
|
@ -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
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
148
goal_src/kernel-defs.gc
Normal file
148
goal_src/kernel-defs.gc
Normal file
|
@ -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*
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
7
goal_src/test/test-declare-inline.gc
Normal file
7
goal_src/test/test-declare-inline.gc
Normal file
|
@ -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)
|
1
goal_src/test/test-floating-point-1.gc
Normal file
1
goal_src/test/test-floating-point-1.gc
Normal file
|
@ -0,0 +1 @@
|
|||
1.234
|
7
goal_src/test/test-inline-call.gc
Normal file
7
goal_src/test/test-inline-call.gc
Normal file
|
@ -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))
|
1
goal_src/test/test-string-symbol.gc
Normal file
1
goal_src/test/test-string-symbol.gc
Normal file
|
@ -0,0 +1 @@
|
|||
(print (string->symbol "test-string"))
|
|
@ -206,7 +206,7 @@ std::vector<std::string> Compiler::run_test(const std::string& source_code) {
|
|||
|
||||
std::vector<std::string> 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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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<FunctionEnv> 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
|
||||
|
|
|
@ -90,6 +90,10 @@ class FileEnv : public Env {
|
|||
void debug_print_tl();
|
||||
const std::vector<std::unique_ptr<FunctionEnv>>& functions() { return m_functions; }
|
||||
const std::vector<std::unique_ptr<StaticObject>>& 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> ir) override;
|
||||
void finish();
|
||||
RegVal* make_ireg(TypeSpec ts, emitter::RegKind kind) override;
|
||||
const std::vector<std::unique_ptr<IR>>& code() { return m_code; }
|
||||
const std::vector<std::unique_ptr<IR>>& code() const { return m_code; }
|
||||
int max_vars() const { return m_iregs.size(); }
|
||||
const std::vector<IRegConstraint>& 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<UnresolvedGoto> unresolved_gotos;
|
||||
std::unordered_map<std::string, Val*> params;
|
||||
|
||||
|
@ -181,7 +185,6 @@ class FunctionEnv : public DeclareEnv {
|
|||
std::vector<IRegConstraint> m_constraints;
|
||||
// todo, unresolved gotos
|
||||
AllocationResult m_regalloc_result;
|
||||
bool m_is_asm_func = false;
|
||||
|
||||
bool m_aligned_stack_required = false;
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
|
@ -403,3 +407,38 @@ void IR_IntegerMath::do_codegen(emitter::ObjectGenerator* gen,
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -13,6 +13,9 @@ uint32_t push_data_to_byte_vector(T data, std::vector<uint8_t>& v) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
////////////////
|
||||
// StaticString
|
||||
////////////////
|
||||
StaticString::StaticString(std::string data, int _seg) : text(std::move(data)), seg(_seg) {}
|
||||
|
||||
std::string StaticString::print() const {
|
||||
|
@ -49,3 +52,32 @@ 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<float>(value, d);
|
||||
}
|
||||
|
||||
int StaticFloat::get_addr_offset() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string StaticFloat::print() const {
|
||||
return fmt::format("(sf {})", value);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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<IR_RegSet>(re, rv));
|
||||
return re;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,3 +78,9 @@ RegVal* LambdaVal::to_reg(Env* fe) {
|
|||
fe->emit(std::make_unique<IR_FunctionAddr>(re, func));
|
||||
return re;
|
||||
}
|
||||
|
||||
RegVal* FloatConstantVal::to_reg(Env* fe) {
|
||||
auto re = fe->make_xmm(m_ts);
|
||||
fe->emit(std::make_unique<IR_StaticVarLoad>(re, m_value));
|
||||
return re;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
@ -256,3 +254,17 @@ Val* Compiler::compile_string(const std::string& str, Env* env, int seg) {
|
|||
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<StaticFloat>(value, seg);
|
||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
||||
auto result = fe->alloc_val<FloatConstantVal>(m_ts.make_typespec("float"), obj.get());
|
||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
||||
fie->add_static(std::move(obj));
|
||||
return result;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
@ -360,3 +361,48 @@ Val* Compiler::compile_real_function_call(const goos::Object& form,
|
|||
return return_reg;
|
||||
}
|
||||
}
|
||||
|
||||
Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto& settings = get_parent_env_of_type<DeclareEnv>(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<FunctionEnv>(env)->is_asm_func = true;
|
||||
}
|
||||
|
||||
else {
|
||||
throw_compile_error(first, "unrecognized declare statement");
|
||||
}
|
||||
});
|
||||
return get_none();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<IR_FunctionCall*>(x.get()), nullptr);
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(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<IR_FunctionCall*>(x.get())) {
|
||||
got_call++;
|
||||
}
|
||||
auto as_im = dynamic_cast<IR_IntegerMath*>(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();
|
||||
|
|
Loading…
Reference in a new issue