mirror of
https://github.com/open-goal/jak-project
synced 2026-05-30 08:56:59 -04:00
add cond with else
This commit is contained in:
@@ -64,6 +64,58 @@ void insert_cfg_into_list(Function& f,
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<IR_Branch*, std::vector<std::shared_ptr<IR>>*> get_condition_branch_as_vector(IR* in) {
|
||||
auto as_seq = dynamic_cast<IR_Begin*>(in);
|
||||
if (as_seq) {
|
||||
auto irb = dynamic_cast<IR_Branch*>(as_seq->forms.back().get());
|
||||
auto loc = &as_seq->forms;
|
||||
assert(irb);
|
||||
return std::make_pair(irb, loc);
|
||||
}
|
||||
return std::make_pair(nullptr, nullptr);
|
||||
}
|
||||
|
||||
std::pair<IR_Branch*, std::shared_ptr<IR>*> get_condition_branch(std::shared_ptr<IR>* in) {
|
||||
IR_Branch* condition_branch = dynamic_cast<IR_Branch*>(in->get());
|
||||
std::shared_ptr<IR>* condition_branch_location = in;
|
||||
if (!condition_branch) {
|
||||
// not 100% sure this will always work
|
||||
auto as_seq = dynamic_cast<IR_Begin*>(in->get());
|
||||
if (as_seq) {
|
||||
condition_branch = dynamic_cast<IR_Branch*>(as_seq->forms.back().get());
|
||||
condition_branch_location = &as_seq->forms.back();
|
||||
}
|
||||
}
|
||||
return std::make_pair(condition_branch, condition_branch_location);
|
||||
}
|
||||
|
||||
void clean_up_cond_with_else(IR_CondWithElse* cwe, LinkedObjectFile& file) {
|
||||
for (auto& e : cwe->entries) {
|
||||
auto jump_to_next = get_condition_branch(&e.condition);
|
||||
assert(jump_to_next.first);
|
||||
assert(jump_to_next.first->branch_delay.kind == BranchDelay::NOP);
|
||||
printf("got cond condition %s\n", jump_to_next.first->print(file).c_str());
|
||||
auto replacement = std::make_shared<IR_Compare>(jump_to_next.first->condition);
|
||||
*(jump_to_next.second) = replacement;
|
||||
|
||||
auto jump_to_end = get_condition_branch(&e.body);
|
||||
assert(jump_to_end.first);
|
||||
assert(jump_to_end.first->branch_delay.kind == BranchDelay::NOP);
|
||||
assert(jump_to_end.first->condition.kind == Condition::ALWAYS);
|
||||
auto as_end_of_sequence = get_condition_branch_as_vector(e.body.get());
|
||||
if (as_end_of_sequence.first) {
|
||||
assert(as_end_of_sequence.second->size() > 1);
|
||||
as_end_of_sequence.second->pop_back();
|
||||
} else {
|
||||
// this means the case is empty, which is a little bit weird but does actually appear to
|
||||
// happen in a few places. so we just replace the jump with a nop. In the future we could
|
||||
// consider having a more explicit "this case is empty" operator so this doesn't get confused
|
||||
// with an actual MIPS nop.
|
||||
*(jump_to_end.second) = std::make_shared<IR_Nop>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx) {
|
||||
if (dynamic_cast<BlockVtx*>(vtx)) {
|
||||
auto* bv = dynamic_cast<BlockVtx*>(vtx);
|
||||
@@ -97,6 +149,19 @@ std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx)
|
||||
auto result = std::make_shared<IR_WhileLoop>(cfg_to_ir(f, file, wvtx->condition),
|
||||
cfg_to_ir(f, file, wvtx->body));
|
||||
return result;
|
||||
} else if (dynamic_cast<CondWithElse*>(vtx)) {
|
||||
auto* cvtx = dynamic_cast<CondWithElse*>(vtx);
|
||||
std::vector<IR_CondWithElse::Entry> entries;
|
||||
for (auto& x : cvtx->entries) {
|
||||
IR_CondWithElse::Entry e;
|
||||
e.condition = cfg_to_ir(f, file, x.condition);
|
||||
e.body = cfg_to_ir(f, file, x.body);
|
||||
entries.push_back(std::move(e));
|
||||
}
|
||||
auto else_ir = cfg_to_ir(f, file, cvtx->else_vtx);
|
||||
auto result = std::make_shared<IR_CondWithElse>(entries, else_ir);
|
||||
clean_up_cond_with_else(result.get(), file);
|
||||
return result;
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -121,22 +186,14 @@ void clean_up_while_loops(IR_Begin* sequence, LinkedObjectFile& file) {
|
||||
to_remove.push_back(i - 1);
|
||||
|
||||
// now we should try to find the condition branch:
|
||||
IR_Branch* condition_branch = dynamic_cast<IR_Branch*>(form_as_while->condition.get());
|
||||
std::shared_ptr<IR>* condition_branch_location = &form_as_while->condition;
|
||||
if (!condition_branch) {
|
||||
// not 100% sure this will always work
|
||||
auto as_seq = dynamic_cast<IR_Begin*>(form_as_while->condition.get());
|
||||
if (as_seq) {
|
||||
condition_branch = dynamic_cast<IR_Branch*>(as_seq->forms.back().get());
|
||||
condition_branch_location = &as_seq->forms.back();
|
||||
}
|
||||
}
|
||||
|
||||
assert(condition_branch);
|
||||
assert(condition_branch->branch_delay.kind == BranchDelay::NOP);
|
||||
printf("got while condition branch %s\n", condition_branch->print(file).c_str());
|
||||
auto replacement = std::make_shared<IR_Compare>(condition_branch->condition);
|
||||
*condition_branch_location = replacement;
|
||||
auto condition_branch = get_condition_branch(&form_as_while->condition);
|
||||
|
||||
assert(condition_branch.first);
|
||||
assert(condition_branch.first->branch_delay.kind == BranchDelay::NOP);
|
||||
printf("got while condition branch %s\n", condition_branch.first->print(file).c_str());
|
||||
auto replacement = std::make_shared<IR_Compare>(condition_branch.first->condition);
|
||||
*(condition_branch.second) = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -493,6 +493,7 @@ std::shared_ptr<Form> IR_Begin::to_form(const LinkedObjectFile& file) const {
|
||||
return buildList(list);
|
||||
}
|
||||
|
||||
|
||||
void IR_Begin::get_children(std::vector<std::shared_ptr<IR>>* output) const {
|
||||
for (auto& x : forms) {
|
||||
output->push_back(x);
|
||||
@@ -525,4 +526,29 @@ std::shared_ptr<Form> IR_WhileLoop::to_form(const LinkedObjectFile& file) const
|
||||
void IR_WhileLoop::get_children(std::vector<std::shared_ptr<IR>>* output) const {
|
||||
output->push_back(condition);
|
||||
output->push_back(body);
|
||||
}
|
||||
|
||||
std::shared_ptr<Form> IR_CondWithElse::to_form(const LinkedObjectFile& file) const {
|
||||
// todo - special case to print as if with else
|
||||
std::vector<std::shared_ptr<Form>> list;
|
||||
list.push_back(toForm("cond"));
|
||||
for(auto& e : entries) {
|
||||
std::vector<std::shared_ptr<Form>> entry;
|
||||
entry.push_back(e.condition->to_form(file));
|
||||
print_inlining_begin(&entry, e.body.get(), file);
|
||||
list.push_back(buildList(entry));
|
||||
}
|
||||
std::vector<std::shared_ptr<Form>> else_form;
|
||||
else_form.push_back(toForm("else"));
|
||||
print_inlining_begin(&else_form, else_ir.get(), file);
|
||||
list.push_back(buildList(else_form));
|
||||
return buildList(list);
|
||||
}
|
||||
|
||||
void IR_CondWithElse::get_children(std::vector<std::shared_ptr<IR>>* output) const {
|
||||
for(auto& e : entries) {
|
||||
output->push_back(e.condition);
|
||||
output->push_back(e.body);
|
||||
}
|
||||
output->push_back(else_ir);
|
||||
}
|
||||
@@ -279,4 +279,18 @@ class IR_WhileLoop : public IR {
|
||||
std::shared_ptr<IR> condition, body;
|
||||
};
|
||||
|
||||
class IR_CondWithElse : public IR {
|
||||
public:
|
||||
struct Entry {
|
||||
std::shared_ptr<IR> condition = nullptr;
|
||||
std::shared_ptr<IR> body = nullptr;
|
||||
};
|
||||
std::vector<Entry> entries;
|
||||
std::shared_ptr<IR> else_ir;
|
||||
IR_CondWithElse(std::vector<Entry> _entries, std::shared_ptr<IR> _else_ir)
|
||||
: entries(std::move(_entries)), else_ir(std::move(_else_ir)) {}
|
||||
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
|
||||
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
|
||||
};
|
||||
|
||||
#endif // JAK_IR_H
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
"vif1-handler-debug", "entity-actor-count", "decompress-frame-data-pair-to-accumulator",
|
||||
"decompress-frame-data-to-accumulator", "normalize-frame-quaternions", "clear-frame-accumulator",
|
||||
"generic-copy-vtx-dclr-dtex", "generic-no-light-dproc-only", "generic-no-light-proc", "mercneric-bittable-asm",
|
||||
"generic-tie-decompress",
|
||||
"generic-tie-decompress", "matrix-axis-sin-cos!", "matrix-axis-sin-cos-vu!", "generic-prepare-dma-single",
|
||||
"(method 13 collide-shape-prim-sphere)", "(method 14 collide-shape-prim-sphere)", "(method 12 collide-shape-prim-sphere)",
|
||||
"adgif-shader<-texture-with-update!",
|
||||
|
||||
"collide-do-primitives", "draw-bones-check-longest-edge-asm",
|
||||
"sp-launch-particles-var", "(method 15 collide-shape-prim-mesh)", "(method 15 collide-shape-prim-sphere)",
|
||||
|
||||
Reference in New Issue
Block a user