17 of 124 compiler tests passing

This commit is contained in:
water 2020-09-07 19:17:48 -04:00
parent ee4eb9f128
commit 1394cf13cd
21 changed files with 449 additions and 15 deletions

View file

@ -960,7 +960,6 @@ uint64_t _call_goal_asm_win32(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr,
u64 call_goal(Ptr<Function> f, u64 a, u64 b, u64 c, u64 st, void* offset) { u64 call_goal(Ptr<Function> f, u64 a, u64 b, u64 c, u64 st, void* offset) {
// auto st_ptr = (void*)((uint8_t*)(offset) + st); updated for the new compiler! // auto st_ptr = (void*)((uint8_t*)(offset) + st); updated for the new compiler!
void* st_ptr = (void*)st; void* st_ptr = (void*)st;
printf("st is 0x%x\n", st);
void* fptr = f.c(); void* fptr = f.c();
#ifdef __linux__ #ifdef __linux__

View file

@ -0,0 +1,5 @@
(defglobalconstant my-constant 12)
(defglobalconstant my-constant 17)
(defglobalconstant not-my-consant 13)
my-constant

View file

@ -0,0 +1,8 @@
(defmacro get-goos-by-name (name)
;; do the lookup in the goos global environment
(eval name)
)
(defglobalconstant my-constant 18)
(get-goos-by-name my-constant)

View file

@ -0,0 +1,9 @@
(block my-block
1
(goto skip-early-return)
(return-from my-block 2)
(label skip-early-return)
3
)

View file

@ -0,0 +1,11 @@
(block outer-block
1
2
(block inner-block
3
4
(return-from inner-block 7)
5
6
)
)

View file

@ -0,0 +1,11 @@
(block outer-block
1
2
(block inner-block
3
4
(return-from inner-block 7)
5
)
8
)

View file

@ -0,0 +1,11 @@
(block outer-block
1
2
(block inner-block
3
4
(return-from outer-block 7)
5
)
8
)

View file

@ -203,5 +203,6 @@ void Compiler::typecheck(const goos::Object& form,
const TypeSpec& expected, const TypeSpec& expected,
const TypeSpec& actual, const TypeSpec& actual,
const std::string& error_message) { const std::string& error_message) {
(void)form;
m_ts.typecheck(expected, actual, error_message, true, true); m_ts.typecheck(expected, actual, error_message, true, true);
} }

View file

@ -53,6 +53,9 @@ class Compiler {
named); named);
std::string as_string(const goos::Object& o); std::string as_string(const goos::Object& o);
std::string symbol_string(const goos::Object& o); std::string symbol_string(const goos::Object& o);
const goos::Object& pair_car(const goos::Object& o);
const goos::Object& pair_cdr(const goos::Object& o);
void expect_empty_list(const goos::Object& o);
TypeSystem m_ts; TypeSystem m_ts;
std::unique_ptr<GlobalEnv> m_global_env = nullptr; std::unique_ptr<GlobalEnv> m_global_env = nullptr;
@ -75,6 +78,10 @@ class Compiler {
// Block // Block
Val* compile_begin(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_begin(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_top_level(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_top_level(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_block(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_return_from(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_label(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_goto(const goos::Object& form, const goos::Object& rest, Env* env);
// CompilerControl // CompilerControl
Val* compile_seval(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_seval(const goos::Object& form, const goos::Object& rest, Env* env);
@ -90,6 +97,7 @@ class Compiler {
// Macro // Macro
Val* compile_gscond(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_gscond(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_quote(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_quote(const goos::Object& form, const goos::Object& rest, Env* env);
Val* compile_defglobalconstant(const goos::Object& form, const goos::Object& rest, Env* env);
}; };
#endif // JAK_COMPILER_H #endif // JAK_COMPILER_H

View file

@ -47,6 +47,10 @@ RegVal* Env::make_xmm(TypeSpec ts) {
return make_ireg(std::move(ts), emitter::RegKind::XMM); return make_ireg(std::move(ts), emitter::RegKind::XMM);
} }
std::unordered_map<std::string, Label>& Env::get_label_map() {
return parent()->get_label_map();
}
/////////////////// ///////////////////
// GlobalEnv // GlobalEnv
/////////////////// ///////////////////
@ -123,6 +127,24 @@ void NoEmitEnv::emit(std::unique_ptr<IR> ir) {
throw std::runtime_error("emit into a no-emit env!"); throw std::runtime_error("emit into a no-emit env!");
} }
///////////////////
// BlockEnv
///////////////////
BlockEnv::BlockEnv(Env* parent, std::string _name) : Env(parent), name(std::move(_name)) {}
std::string BlockEnv::print() {
return "block-" + name;
}
BlockEnv* BlockEnv::find_block(const std::string& block) {
if (name == block) {
return this;
} else {
return parent()->find_block(block);
}
}
/////////////////// ///////////////////
// FileEnv // FileEnv
/////////////////// ///////////////////
@ -179,7 +201,17 @@ void FunctionEnv::emit(std::unique_ptr<IR> ir) {
m_code.push_back(std::move(ir)); m_code.push_back(std::move(ir));
} }
void FunctionEnv::finish() { void FunctionEnv::finish() {
// todo resolve gotos resolve_gotos();
}
void FunctionEnv::resolve_gotos() {
for (auto& gt : unresolved_gotos) {
auto kv_label = m_labels.find(gt.label);
if (kv_label == m_labels.end()) {
throw std::runtime_error("Invalid goto " + gt.label);
}
gt.ir->resolve(&kv_label->second);
}
} }
RegVal* FunctionEnv::make_ireg(TypeSpec ts, emitter::RegKind kind) { RegVal* FunctionEnv::make_ireg(TypeSpec ts, emitter::RegKind kind) {
@ -189,4 +221,12 @@ RegVal* FunctionEnv::make_ireg(TypeSpec ts, emitter::RegKind kind) {
auto rv = std::make_unique<RegVal>(ireg, ts); auto rv = std::make_unique<RegVal>(ireg, ts);
m_iregs.push_back(std::move(rv)); m_iregs.push_back(std::move(rv));
return m_iregs.back().get(); return m_iregs.back().get();
}
std::unordered_map<std::string, Label>& FunctionEnv::get_label_map() {
return m_labels;
}
std::unordered_map<std::string, Label>& LabelEnv::get_label_map() {
return m_labels;
} }

View file

@ -33,6 +33,7 @@ class Env {
virtual void constrain_reg(IRegConstraint constraint); virtual void constrain_reg(IRegConstraint constraint);
virtual Val* lexical_lookup(goos::Object sym); virtual Val* lexical_lookup(goos::Object sym);
virtual BlockEnv* find_block(const std::string& name); virtual BlockEnv* find_block(const std::string& name);
virtual std::unordered_map<std::string, Label>& get_label_map();
RegVal* make_gpr(TypeSpec ts); RegVal* make_gpr(TypeSpec ts);
RegVal* make_xmm(TypeSpec ts); RegVal* make_xmm(TypeSpec ts);
virtual ~Env() = default; virtual ~Env() = default;
@ -117,10 +118,18 @@ class DeclareEnv : public Env {
} settings; } settings;
}; };
class IR_GotoLabel;
struct UnresolvedGoto {
IR_GotoLabel* ir;
std::string label;
};
class FunctionEnv : public DeclareEnv { class FunctionEnv : public DeclareEnv {
public: public:
FunctionEnv(Env* parent, std::string name); FunctionEnv(Env* parent, std::string name);
std::string print() override; std::string print() override;
std::unordered_map<std::string, Label>& get_label_map() override;
void set_segment(int seg) { segment = seg; } void set_segment(int seg) { segment = seg; }
void emit(std::unique_ptr<IR> ir) override; void emit(std::unique_ptr<IR> ir) override;
void finish(); void finish();
@ -140,14 +149,26 @@ class FunctionEnv : public DeclareEnv {
m_vals.push_back(std::move(new_obj)); m_vals.push_back(std::move(new_obj));
return (T*)m_vals.back().get(); return (T*)m_vals.back().get();
} }
template <typename T, class... Args>
T* alloc_env(Args&&... args) {
std::unique_ptr<T> new_obj = std::make_unique<T>(std::forward<Args>(args)...);
m_envs.push_back(std::move(new_obj));
return (T*)m_envs.back().get();
}
int segment = -1; int segment = -1;
std::string method_of_type_name = "#f"; std::string method_of_type_name = "#f";
std::vector<UnresolvedGoto> unresolved_gotos;
protected: protected:
void resolve_gotos();
std::string m_name; std::string m_name;
std::vector<std::unique_ptr<IR>> m_code; std::vector<std::unique_ptr<IR>> m_code;
std::vector<std::unique_ptr<RegVal>> m_iregs; std::vector<std::unique_ptr<RegVal>> m_iregs;
std::vector<std::unique_ptr<Val>> m_vals; std::vector<std::unique_ptr<Val>> m_vals;
std::vector<std::unique_ptr<Env>> m_envs;
std::vector<IRegConstraint> m_constraints; std::vector<IRegConstraint> m_constraints;
// todo, unresolved gotos // todo, unresolved gotos
AllocationResult m_regalloc_result; AllocationResult m_regalloc_result;
@ -156,6 +177,7 @@ class FunctionEnv : public DeclareEnv {
bool m_aligned_stack_required = false; bool m_aligned_stack_required = false;
std::unordered_map<std::string, Env*> m_params; std::unordered_map<std::string, Env*> m_params;
std::unordered_map<std::string, Label> m_labels;
}; };
class BlockEnv : public Env { class BlockEnv : public Env {
@ -164,11 +186,10 @@ class BlockEnv : public Env {
std::string print() override; std::string print() override;
BlockEnv* find_block(const std::string& name) override; BlockEnv* find_block(const std::string& name) override;
protected: std::string name;
std::string m_name; Label end_label = nullptr;
Label* m_end_label = nullptr; RegVal* return_value = nullptr;
Val* m_return_value = nullptr; std::vector<TypeSpec> return_types;
std::vector<TypeSpec> m_return_types;
}; };
class LexicalEnv : public Env { class LexicalEnv : public Env {
@ -179,6 +200,8 @@ class LexicalEnv : public Env {
class LabelEnv : public Env { class LabelEnv : public Env {
public: public:
std::unordered_map<std::string, Label>& get_label_map() override;
protected: protected:
std::unordered_map<std::string, Label> m_labels; std::unordered_map<std::string, Label> m_labels;
}; };

View file

@ -168,4 +168,75 @@ void IR_GetSymbolValue::do_codegen(emitter::ObjectGenerator* gen,
irec); irec);
gen->link_instruction_symbol_mem(instr, m_src->name()); gen->link_instruction_symbol_mem(instr, m_src->name());
} }
}
/////////////////////
// RegSet
/////////////////////
IR_RegSet::IR_RegSet(const RegVal* dest, const RegVal* src) : m_dest(dest), m_src(src) {}
RegAllocInstr IR_RegSet::to_rai() {
RegAllocInstr rai;
rai.write.push_back(m_dest->ireg());
rai.read.push_back(m_src->ireg());
if (m_dest->ireg().kind == m_src->ireg().kind) {
rai.is_move = true; // only true if we aren't moving from register kind to register kind
}
return rai;
}
void IR_RegSet::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
auto val_reg = get_reg(m_src, allocs, irec);
auto dest_reg = get_reg(m_dest, allocs, irec);
if (val_reg == dest_reg) {
gen->add_instr(IGen::null(), irec);
} else {
gen->add_instr(IGen::mov_gpr64_gpr64(dest_reg, val_reg), irec);
}
}
std::string IR_RegSet::print() {
return fmt::format("mov {}, {}", m_dest->print(), m_src->print());
}
/////////////////////
// GotoLabel
/////////////////////
IR_GotoLabel::IR_GotoLabel(const Label* dest) : m_dest(dest) {
m_resolved = true;
}
IR_GotoLabel::IR_GotoLabel() {
m_resolved = false;
}
std::string IR_GotoLabel::print() {
return fmt::format("goto {}", m_dest->print());
}
RegAllocInstr IR_GotoLabel::to_rai() {
assert(m_resolved);
RegAllocInstr rai;
rai.jumps.push_back(m_dest->idx);
rai.fallthrough = false;
return rai;
}
void IR_GotoLabel::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
(void)allocs;
auto instr = gen->add_instr(IGen::jmp_32(), irec);
gen->link_instruction_jump(instr, gen->get_future_ir_record_in_same_func(irec, m_dest->idx));
}
void IR_GotoLabel::resolve(const Label* dest) {
assert(!m_resolved);
m_dest = dest;
m_resolved = true;
} }

View file

@ -99,4 +99,34 @@ class IR_GetSymbolValue : public IR {
bool m_sext = false; bool m_sext = false;
}; };
class IR_RegSet : public IR {
public:
IR_RegSet(const RegVal* dest, const RegVal* 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 RegVal* m_src = nullptr;
};
class IR_GotoLabel : public IR {
public:
IR_GotoLabel();
void resolve(const Label* dest);
explicit IR_GotoLabel(const Label* dest);
std::string print() override;
RegAllocInstr to_rai() override;
void do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) override;
protected:
const Label* m_dest = nullptr;
bool m_resolved = false;
};
#endif // JAK_IR_H #endif // JAK_IR_H

View file

@ -1,8 +1,13 @@
#ifndef JAK_LABEL_H #ifndef JAK_LABEL_H
#define JAK_LABEL_H #define JAK_LABEL_H
struct Label {}; class FunctionEnv;
struct Label {
Label() = default;
Label(FunctionEnv* f, int _idx = -1) : func(f), idx(_idx) {}
FunctionEnv* func = nullptr;
int idx = -1;
std::string print() const { return "label-" + std::to_string(idx); }
};
#endif // JAK_LABEL_H #endif // JAK_LABEL_H

View file

@ -103,4 +103,18 @@ std::string Compiler::as_string(const goos::Object& o) {
std::string Compiler::symbol_string(const goos::Object& o) { std::string Compiler::symbol_string(const goos::Object& o) {
return o.as_symbol()->name; return o.as_symbol()->name;
}
const goos::Object& Compiler::pair_car(const goos::Object& o) {
return o.as_pair()->car;
}
const goos::Object& Compiler::pair_cdr(const goos::Object& o) {
return o.as_pair()->cdr;
}
void Compiler::expect_empty_list(const goos::Object& o) {
if (!o.is_empty_list()) {
throw_compile_error(o, "expected to be an empty list");
}
} }

View file

@ -19,10 +19,10 @@ static const std::unordered_map<
// // BLOCK FORMS // // BLOCK FORMS
{"top-level", &Compiler::compile_top_level}, {"top-level", &Compiler::compile_top_level},
{"begin", &Compiler::compile_begin}, {"begin", &Compiler::compile_begin},
// {"block", &Compiler::compile_block}, {"block", &Compiler::compile_block},
// {"return-from", &Compiler::compile_return_from}, {"return-from", &Compiler::compile_return_from},
// {"label", &Compiler::compile_label}, {"label", &Compiler::compile_label},
// {"goto", &Compiler::compile_goto}, {"goto", &Compiler::compile_goto},
// //
// // COMPILER CONTROL // // COMPILER CONTROL
// {"gs", &Compiler::compile_gs}, // {"gs", &Compiler::compile_gs},
@ -36,7 +36,7 @@ static const std::unordered_map<
// //
// // CONDITIONAL COMPILATION // // CONDITIONAL COMPILATION
{"#cond", &Compiler::compile_gscond}, {"#cond", &Compiler::compile_gscond},
// {"defglobalconstant", &Compiler::compile_defglobalconstant}, {"defglobalconstant", &Compiler::compile_defglobalconstant},
{"seval", &Compiler::compile_seval}, {"seval", &Compiler::compile_seval},
// //
// // CONTROL FLOW // // CONTROL FLOW
@ -200,6 +200,21 @@ Val* Compiler::compile_symbol(const goos::Object& form, Env* env) {
// todo lexical // todo lexical
// todo global constant // todo global constant
auto global_constant = m_global_constants.find(form.as_symbol());
auto existing_symbol = m_symbol_types.find(form.as_symbol()->name);
if (global_constant != m_global_constants.end()) {
// check there is no symbol with the same name
if (existing_symbol != m_symbol_types.end()) {
throw_compile_error(form,
"symbol is both a runtime symbol and a global constant. Something is "
"likely very wrong.");
}
// got a global constant
return compile_error_guard(global_constant->second, env);
}
return compile_get_symbol_value(name, env); return compile_get_symbol_value(name, env);
} }

View file

@ -13,3 +13,132 @@ Val* Compiler::compile_begin(const goos::Object& form, const goos::Object& rest,
for_each_in_list(rest, [&](const Object& o) { result = compile_error_guard(o, env); }); for_each_in_list(rest, [&](const Object& o) { result = compile_error_guard(o, env); });
return result; return result;
} }
Val* Compiler::compile_block(const goos::Object& form, const goos::Object& _rest, Env* env) {
auto rest = &_rest;
auto name = pair_car(*rest);
rest = &pair_cdr(*rest);
if (!rest->is_pair()) {
throw_compile_error(form, "Block form has an empty or invliad body");
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
// create environment
auto block_env = fe->alloc_env<BlockEnv>(env, symbol_string(name));
// we need to create a return value register, as a "return-from" statement inside the block may
// set it. for now it has a type of none, but we will set it more accurate after compiling the
// block.
// block_env->return_value = env->alloc_reg(get_base_typespec("none"));
block_env->return_value = env->make_gpr(m_ts.make_typespec("none"));
// create label to the end of the block (we don't yet know where it is...)
block_env->end_label = Label(fe);
// compile everything in the body
Val* result = get_none();
for_each_in_list(*rest, [&](const Object& o) { result = compile_error_guard(o, block_env); });
// if no return-from's were used, we can ignore the return_value register, and basically turn this
// into a begin. this allows a block which returns a floating point value to return the value in
// an xmm register, which is likely to eliminate a gpr->xmm move.
if (block_env->return_types.empty()) {
return result;
}
// determine return type as the lowest common ancestor of the block's last form and any
// return-from's
auto& return_types = block_env->return_types;
return_types.push_back(result->type());
auto return_type = m_ts.lowest_common_ancestor(return_types);
block_env->return_value->set_type(return_type);
// an IR to move the result of the block into the block's return register (if no return-from's are
// taken)
auto ir_move_rv = std::make_unique<IR_RegSet>(block_env->return_value, result->to_gpr(fe));
// note - one drawback of doing this single pass is that a block always evaluates to a gpr.
// so we may have an unneeded xmm -> gpr move that could have been an xmm -> xmm that could have
// been eliminated.
env->emit(std::move(ir_move_rv));
// now we know the end of the block, so we set the label index to be on whatever comes after the
// return move. functions always end with a "null" IR and "null" instruction, so this is safe.
block_env->end_label.idx = block_env->end_label.func->code().size();
return block_env->return_value;
}
Val* Compiler::compile_return_from(const goos::Object& form, const goos::Object& _rest, Env* env) {
const Object* rest = &_rest;
auto block_name = symbol_string(pair_car(*rest));
rest = &pair_cdr(*rest);
auto value_expression = pair_car(*rest);
expect_empty_list(pair_cdr(*rest));
// evaluate expression to return
auto result = compile_error_guard(value_expression, env);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
// find block to return from
auto block = dynamic_cast<BlockEnv*>(env->find_block(block_name));
if (!block) {
throw_compile_error(form,
"The return-from form was unable to find a block named " + block_name);
}
// move result into return register
auto ir_move_rv = std::make_unique<IR_RegSet>(block->return_value, result->to_gpr(fe));
// inform block of our possible return type
block->return_types.push_back(result->type());
env->emit(std::move(ir_move_rv));
// jump to end of block
auto ir_jump = std::make_unique<IR_GotoLabel>(&block->end_label);
// we know this label is a real label. even though end_label doesn't know where it is, there is an
// actual label object. this means we won't try to resolve this label _by name_ later on when the
// block is done.
// ir_jump->resolved = true;
env->emit(std::move(ir_jump));
// In the real GOAL, there is likely a bug here where a non-none value is returned.
return get_none();
}
Val* Compiler::compile_label(const goos::Object& form, const goos::Object& rest, Env* env) {
auto label_name = symbol_string(pair_car(rest));
expect_empty_list(pair_cdr(rest));
// make sure we don't have a label with this name already
auto& labels = env->get_label_map();
auto kv = labels.find(label_name);
if (kv != labels.end()) {
throw_compile_error(
form, "There are two labels named " + label_name + " in the same label environment");
}
// make a label pointing to the end of the current function env.
auto func_env = get_parent_env_of_type<FunctionEnv>(env);
labels[label_name] = Label(func_env, func_env->code().size());
return get_none();
}
Val* Compiler::compile_goto(const goos::Object& form, const goos::Object& rest, Env* env) {
(void)form;
auto label_name = symbol_string(pair_car(rest));
expect_empty_list(pair_cdr(rest));
auto ir_goto = std::make_unique<IR_GotoLabel>();
// this requires looking up the label by name after, as it may be a goto to a label which has not
// yet been defined.
// add this goto to the list of gotos to resolve after the function is done.
// it's safe to have this reference, as the FunctionEnv also owns the goto.
get_parent_env_of_type<FunctionEnv>(env)->unresolved_gotos.push_back({ir_goto.get(), label_name});
env->emit(std::move(ir_goto));
return get_none();
}

View file

@ -28,6 +28,7 @@ Val* Compiler::compile_goos_macro(const goos::Object& o,
Arguments args = m_goos.get_args(o, rest, macro->args); Arguments args = m_goos.get_args(o, rest, macro->args);
auto mac_env_obj = EnvironmentObject::make_new(); auto mac_env_obj = EnvironmentObject::make_new();
auto mac_env = mac_env_obj.as_env(); auto mac_env = mac_env_obj.as_env();
mac_env->parent_env = m_goos.global_environment.as_env();
m_goos.set_args_in_env(o, args, macro->args, mac_env); m_goos.set_args_in_env(o, args, macro->args, mac_env);
m_goos.goal_to_goos.enclosing_method_type = m_goos.goal_to_goos.enclosing_method_type =
get_parent_env_of_type<FunctionEnv>(env)->method_of_type_name; get_parent_env_of_type<FunctionEnv>(env)->method_of_type_name;
@ -85,5 +86,32 @@ Val* Compiler::compile_quote(const goos::Object& form, const goos::Object& rest,
default: default:
throw_compile_error(form, "Can't quote this"); throw_compile_error(form, "Can't quote this");
} }
return get_none();
}
Val* Compiler::compile_defglobalconstant(const goos::Object& form,
const goos::Object& _rest,
Env* env) {
auto rest = &_rest;
(void)env;
if (!rest->is_pair()) {
throw_compile_error(form, "invalid defglobalconstant");
}
auto sym = pair_car(*rest).as_symbol();
rest = &pair_cdr(*rest);
auto value = pair_car(*rest);
rest = &rest->as_pair()->cdr;
if (!rest->is_empty_list()) {
throw_compile_error(form, "invalid defglobalconstant");
}
// GOAL constant
m_global_constants[sym] = value;
// GOOS constant
m_goos.global_environment.as_env()->vars[sym] = value;
return get_none(); return get_none();
} }

View file

@ -136,6 +136,15 @@ IR_Record ObjectGenerator::get_future_ir_record(const FunctionRecord& func, int
return rec; return rec;
} }
IR_Record ObjectGenerator::get_future_ir_record_in_same_func(const IR_Record& irec, int ir_id) {
assert(irec.func_id == int(m_function_data_by_seg.at(irec.seg).size()) - 1);
IR_Record rec;
rec.seg = irec.seg;
rec.func_id = irec.func_id;
rec.ir_id = ir_id;
return rec;
}
/*! /*!
* Add a new Instruction for the given IR instruction. * Add a new Instruction for the given IR instruction.
*/ */

View file

@ -43,6 +43,7 @@ class ObjectGenerator {
int min_align = 16); // should align and insert function tag int min_align = 16); // should align and insert function tag
IR_Record add_ir(const FunctionRecord& func); IR_Record add_ir(const FunctionRecord& func);
IR_Record get_future_ir_record(const FunctionRecord& func, int ir_id); IR_Record get_future_ir_record(const FunctionRecord& func, int ir_id);
IR_Record get_future_ir_record_in_same_func(const IR_Record& irec, int ir_id);
InstructionRecord add_instr(Instruction inst, IR_Record ir); InstructionRecord add_instr(Instruction inst, IR_Record ir);
void add_instr_no_ir(FunctionRecord func, Instruction inst); void add_instr_no_ir(FunctionRecord func, Instruction inst);
StaticRecord add_static_to_seg(int seg, int min_align = 16); StaticRecord add_static_to_seg(int seg, int min_align = 16);

View file

@ -111,6 +111,12 @@ TEST(CompilerAndRuntime, CompilerTests) {
runner.run_test("test-get-symbol-1.gc", {"1342756\n"}); // 0x147d24 in hex runner.run_test("test-get-symbol-1.gc", {"1342756\n"}); // 0x147d24 in hex
runner.run_test("test-get-symbol-2.gc", {"1342764\n"}); // 0x147d2c in hex runner.run_test("test-get-symbol-2.gc", {"1342764\n"}); // 0x147d2c in hex
runner.run_test("test-define-1.gc", {"17\n"}); runner.run_test("test-define-1.gc", {"17\n"});
runner.run_test("test-nested-blocks-1.gc", {"7\n"});
runner.run_test("test-nested-blocks-2.gc", {"8\n"});
runner.run_test("test-nested-blocks-3.gc", {"7\n"});
runner.run_test("test-goto-1.gc", {"3\n"});
runner.run_test("test-defglobalconstant-1.gc", {"17\n"});
runner.run_test("test-defglobalconstant-2.gc", {"18\n"});
compiler.shutdown_target(); compiler.shutdown_target();
runtime_thread.join(); runtime_thread.join();