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
|
;; BUILD SYSTEM
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -23,13 +33,11 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
;; load list of all goal files
|
|
||||||
(asm-file "goal_src/build/all_files.gc")
|
|
||||||
|
|
||||||
(defmacro e ()
|
(defmacro e ()
|
||||||
`(:exit)
|
`(:exit)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; CONDITIONAL COMPILATION
|
;; 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
|
;; name in dgo: gcommon
|
||||||
;; dgos: KERNEL
|
;; 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) {
|
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 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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ class Compiler {
|
||||||
Compiler();
|
Compiler();
|
||||||
~Compiler();
|
~Compiler();
|
||||||
void execute_repl();
|
void execute_repl();
|
||||||
|
goos::Interpreter& get_goos() { return m_goos; }
|
||||||
FileEnv* compile_object_file(const std::string& name, goos::Object code, bool allow_emit);
|
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,
|
std::unique_ptr<FunctionEnv> compile_top_level_function(const std::string& name,
|
||||||
const goos::Object& code,
|
const goos::Object& code,
|
||||||
|
@ -40,6 +41,8 @@ class Compiler {
|
||||||
Val* compile_pair(const goos::Object& code, Env* env);
|
Val* compile_pair(const goos::Object& code, Env* env);
|
||||||
Val* compile_integer(const goos::Object& code, Env* env);
|
Val* compile_integer(const goos::Object& code, Env* env);
|
||||||
Val* compile_integer(s64 value, 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_symbol(const goos::Object& form, Env* env);
|
||||||
Val* compile_string(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);
|
Val* compile_string(const std::string& str, Env* env, int seg = MAIN_SEGMENT);
|
||||||
|
@ -137,6 +140,7 @@ class Compiler {
|
||||||
// Function
|
// Function
|
||||||
Val* compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env);
|
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_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
|
#endif // JAK_COMPILER_H
|
||||||
|
|
|
@ -90,6 +90,10 @@ class FileEnv : public Env {
|
||||||
void debug_print_tl();
|
void debug_print_tl();
|
||||||
const std::vector<std::unique_ptr<FunctionEnv>>& functions() { return m_functions; }
|
const std::vector<std::unique_ptr<FunctionEnv>>& functions() { return m_functions; }
|
||||||
const std::vector<std::unique_ptr<StaticObject>>& statics() { return m_statics; }
|
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();
|
bool is_empty();
|
||||||
~FileEnv() = default;
|
~FileEnv() = default;
|
||||||
|
@ -137,7 +141,7 @@ class FunctionEnv : public DeclareEnv {
|
||||||
void emit(std::unique_ptr<IR> ir) override;
|
void emit(std::unique_ptr<IR> ir) override;
|
||||||
void finish();
|
void finish();
|
||||||
RegVal* make_ireg(TypeSpec ts, emitter::RegKind kind) override;
|
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(); }
|
int max_vars() const { return m_iregs.size(); }
|
||||||
const std::vector<IRegConstraint>& constraints() { return m_constraints; }
|
const std::vector<IRegConstraint>& constraints() { return m_constraints; }
|
||||||
void constrain(const IRegConstraint& c) { m_constraints.push_back(c); }
|
void constrain(const IRegConstraint& c) { m_constraints.push_back(c); }
|
||||||
|
@ -167,7 +171,7 @@ class FunctionEnv : public DeclareEnv {
|
||||||
|
|
||||||
int segment = -1;
|
int segment = -1;
|
||||||
std::string method_of_type_name = "#f";
|
std::string method_of_type_name = "#f";
|
||||||
|
bool is_asm_func = false;
|
||||||
std::vector<UnresolvedGoto> unresolved_gotos;
|
std::vector<UnresolvedGoto> unresolved_gotos;
|
||||||
std::unordered_map<std::string, Val*> params;
|
std::unordered_map<std::string, Val*> params;
|
||||||
|
|
||||||
|
@ -181,7 +185,6 @@ class FunctionEnv : public DeclareEnv {
|
||||||
std::vector<IRegConstraint> m_constraints;
|
std::vector<IRegConstraint> m_constraints;
|
||||||
// todo, unresolved gotos
|
// todo, unresolved gotos
|
||||||
AllocationResult m_regalloc_result;
|
AllocationResult m_regalloc_result;
|
||||||
bool m_is_asm_func = false;
|
|
||||||
|
|
||||||
bool m_aligned_stack_required = false;
|
bool m_aligned_stack_required = false;
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,12 @@ void IR_RegSet::do_codegen(emitter::ObjectGenerator* gen,
|
||||||
|
|
||||||
if (val_reg == dest_reg) {
|
if (val_reg == dest_reg) {
|
||||||
gen->add_instr(IGen::null(), irec);
|
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);
|
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
|
// FunctionAddr
|
||||||
///////////////////
|
/////////////////////
|
||||||
|
|
||||||
IR_FunctionAddr::IR_FunctionAddr(const RegVal* dest, FunctionEnv* src) : m_dest(dest), m_src(src) {}
|
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
|
// IntegerMath
|
||||||
///////////////////
|
/////////////////////
|
||||||
|
|
||||||
IR_IntegerMath::IR_IntegerMath(IntegerMathKind kind, RegVal* dest, RegVal* arg)
|
IR_IntegerMath::IR_IntegerMath(IntegerMathKind kind, RegVal* dest, RegVal* arg)
|
||||||
: m_kind(kind), m_dest(dest), m_arg(arg) {}
|
: m_kind(kind), m_dest(dest), m_arg(arg) {}
|
||||||
|
@ -403,3 +407,38 @@ void IR_IntegerMath::do_codegen(emitter::ObjectGenerator* gen,
|
||||||
assert(false);
|
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;
|
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 {
|
class IR_FunctionAddr : public IR {
|
||||||
public:
|
public:
|
||||||
IR_FunctionAddr(const RegVal* dest, FunctionEnv* src);
|
IR_FunctionAddr(const RegVal* dest, FunctionEnv* src);
|
||||||
|
@ -199,6 +213,7 @@ class IR_IntegerMath : public IR {
|
||||||
void do_codegen(emitter::ObjectGenerator* gen,
|
void do_codegen(emitter::ObjectGenerator* gen,
|
||||||
const AllocationResult& allocs,
|
const AllocationResult& allocs,
|
||||||
emitter::IR_Record irec) override;
|
emitter::IR_Record irec) override;
|
||||||
|
IntegerMathKind get_kind() const { return m_kind; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
IntegerMathKind m_kind;
|
IntegerMathKind m_kind;
|
||||||
|
|
|
@ -13,6 +13,9 @@ uint32_t push_data_to_byte_vector(T data, std::vector<uint8_t>& v) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
////////////////
|
||||||
|
// StaticString
|
||||||
|
////////////////
|
||||||
StaticString::StaticString(std::string data, int _seg) : text(std::move(data)), seg(_seg) {}
|
StaticString::StaticString(std::string data, int _seg) : text(std::move(data)), seg(_seg) {}
|
||||||
|
|
||||||
std::string StaticString::print() const {
|
std::string StaticString::print() const {
|
||||||
|
@ -49,3 +52,32 @@ void StaticString::generate(emitter::ObjectGenerator* gen) {
|
||||||
int StaticString::get_addr_offset() const {
|
int StaticString::get_addr_offset() const {
|
||||||
return BASIC_OFFSET;
|
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;
|
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
|
#endif // JAK_STATICOBJECT_H
|
||||||
|
|
|
@ -6,11 +6,14 @@
|
||||||
* Fallback to_gpr if a more optimized one is not provided.
|
* Fallback to_gpr if a more optimized one is not provided.
|
||||||
*/
|
*/
|
||||||
RegVal* Val::to_gpr(Env* fe) {
|
RegVal* Val::to_gpr(Env* fe) {
|
||||||
|
// TODO - handle 128-bit stuff here!
|
||||||
auto rv = to_reg(fe);
|
auto rv = to_reg(fe);
|
||||||
if (rv->ireg().kind == emitter::RegKind::GPR) {
|
if (rv->ireg().kind == emitter::RegKind::GPR) {
|
||||||
return rv;
|
return rv;
|
||||||
} else {
|
} 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));
|
fe->emit(std::make_unique<IR_FunctionAddr>(re, func));
|
||||||
return re;
|
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 {
|
class FloatConstantVal : public Val {
|
||||||
public:
|
public:
|
||||||
FloatConstantVal(TypeSpec ts, float value) : Val(std::move(ts)), m_value(value) {}
|
FloatConstantVal(TypeSpec ts, StaticFloat* value) : Val(std::move(ts)), m_value(value) {}
|
||||||
std::string print() const override { return "float-constant-" + std::to_string(m_value); }
|
std::string print() const override { return "float-constant-" + m_value->print(); }
|
||||||
RegVal* to_reg(Env* fe) override;
|
RegVal* to_reg(Env* fe) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float m_value = -1.f;
|
StaticFloat* m_value = nullptr;
|
||||||
};
|
};
|
||||||
// IntegerConstant
|
// IntegerConstant
|
||||||
// FloatConstant
|
// FloatConstant
|
||||||
|
|
|
@ -68,7 +68,8 @@ static const std::unordered_map<
|
||||||
//
|
//
|
||||||
// // LAMBDA
|
// // LAMBDA
|
||||||
{"lambda", &Compiler::compile_lambda},
|
{"lambda", &Compiler::compile_lambda},
|
||||||
// {"inline", &Compiler::compile_inline},
|
{"declare", &Compiler::compile_declare},
|
||||||
|
{"inline", &Compiler::compile_inline},
|
||||||
// {"with-inline", &Compiler::compile_with_inline},
|
// {"with-inline", &Compiler::compile_with_inline},
|
||||||
// {"rlet", &Compiler::compile_rlet},
|
// {"rlet", &Compiler::compile_rlet},
|
||||||
// {"mlet", &Compiler::compile_mlet},
|
// {"mlet", &Compiler::compile_mlet},
|
||||||
|
@ -81,11 +82,6 @@ static const std::unordered_map<
|
||||||
{"quote", &Compiler::compile_quote},
|
{"quote", &Compiler::compile_quote},
|
||||||
// {"defconstant", &Compiler::compile_defconstant},
|
// {"defconstant", &Compiler::compile_defconstant},
|
||||||
//
|
//
|
||||||
// {"declare", &Compiler::compile_declare},
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // OBJECT
|
// // OBJECT
|
||||||
//
|
//
|
||||||
// {"the", &Compiler::compile_the},
|
// {"the", &Compiler::compile_the},
|
||||||
|
@ -150,6 +146,8 @@ Val* Compiler::compile(const goos::Object& code, Env* env) {
|
||||||
return compile_symbol(code, env);
|
return compile_symbol(code, env);
|
||||||
case goos::ObjectType::STRING:
|
case goos::ObjectType::STRING:
|
||||||
return compile_string(code, env);
|
return compile_string(code, env);
|
||||||
|
case goos::ObjectType::FLOAT:
|
||||||
|
return compile_float(code, env);
|
||||||
default:
|
default:
|
||||||
ice("Don't know how to compile " + code.print());
|
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));
|
fie->add_static(std::move(obj));
|
||||||
return result;
|
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()) {
|
if (eval_args.empty()) {
|
||||||
throw_compile_error(form, "0 argument method call is impossible to figure out");
|
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
|
assert(false); // nyi
|
||||||
// head = compile_get_method_of_object(eval_args.front(), symbol_string(uneval_head), env);
|
// 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;
|
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) {
|
Val* Compiler::number_to_integer(Val* in, Env* env) {
|
||||||
|
(void)env;
|
||||||
auto ts = in->type();
|
auto ts = in->type();
|
||||||
if (is_binteger(ts)) {
|
if (is_binteger(ts)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -52,6 +53,7 @@ Val* Compiler::number_to_integer(Val* in, Env* env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::number_to_binteger(Val* in, Env* env) {
|
Val* Compiler::number_to_binteger(Val* in, Env* env) {
|
||||||
|
(void)env;
|
||||||
auto ts = in->type();
|
auto ts = in->type();
|
||||||
if (is_binteger(ts)) {
|
if (is_binteger(ts)) {
|
||||||
return in;
|
return in;
|
||||||
|
@ -65,6 +67,7 @@ Val* Compiler::number_to_binteger(Val* in, Env* env) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::number_to_float(Val* in, Env* env) {
|
Val* Compiler::number_to_float(Val* in, Env* env) {
|
||||||
|
(void)env;
|
||||||
auto ts = in->type();
|
auto ts = in->type();
|
||||||
if (is_binteger(ts)) {
|
if (is_binteger(ts)) {
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
|
@ -133,6 +133,48 @@ TEST(CompilerAndRuntime, BuildGame) {
|
||||||
runtime_thread.join();
|
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) {
|
TEST(CompilerAndRuntime, CompilerTests) {
|
||||||
std::thread runtime_thread([]() { exec_runtime(0, nullptr); });
|
std::thread runtime_thread([]() { exec_runtime(0, nullptr); });
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
|
@ -184,6 +226,14 @@ TEST(CompilerAndRuntime, CompilerTests) {
|
||||||
runner.run_test("test-sub-2.gc", {"4\n"});
|
runner.run_test("test-sub-2.gc", {"4\n"});
|
||||||
runner.run_test("test-mul-1.gc", {"-12\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();
|
compiler.shutdown_target();
|
||||||
runtime_thread.join();
|
runtime_thread.join();
|
||||||
runner.print_summary();
|
runner.print_summary();
|
||||||
|
|
Loading…
Reference in a new issue