Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add decompiler IR, basic operations, all-types file #57

Merged
merged 7 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions common/type_system/deftype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,6 @@ int64_t get_int(const goos::Object& obj) {
throw std::runtime_error(obj.print() + " was supposed to be an integer, but isn't");
}

TypeSpec parse_typespec(TypeSystem* type_system, const goos::Object& src) {
if (src.is_symbol()) {
return type_system->make_typespec(symbol_string(src));
} else if (src.is_pair()) {
TypeSpec ts = type_system->make_typespec(symbol_string(car(&src)));
const auto& rest = *cdr(&src);

for_each_in_list(rest,
[&](const goos::Object& o) { ts.add_arg(parse_typespec(type_system, o)); });

return ts;
} else {
throw std::runtime_error("invalid typespec: " + src.print());
}
assert(false);
return {};
}

void add_field(StructureType* structure, TypeSystem* ts, const goos::Object& def) {
auto rest = &def;

Expand Down Expand Up @@ -278,6 +260,24 @@ TypeFlags parse_structure_def(StructureType* type,

} // namespace

TypeSpec parse_typespec(TypeSystem* type_system, const goos::Object& src) {
if (src.is_symbol()) {
return type_system->make_typespec(symbol_string(src));
} else if (src.is_pair()) {
TypeSpec ts = type_system->make_typespec(symbol_string(car(&src)));
const auto& rest = *cdr(&src);

for_each_in_list(rest,
[&](const goos::Object& o) { ts.add_arg(parse_typespec(type_system, o)); });

return ts;
} else {
throw std::runtime_error("invalid typespec: " + src.print());
}
assert(false);
return {};
}

DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) {
auto iter = &deftype;

Expand Down
1 change: 1 addition & 0 deletions common/type_system/deftype.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ struct DeftypeResult {
};

DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts);
TypeSpec parse_typespec(TypeSystem* type_system, const goos::Object& src);
2 changes: 1 addition & 1 deletion decomp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
# Directory of this script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

$DIR/build/decompiler/decompiler $DIR/decompiler/config/jak1_ntsc_black_label.jsonc $DIR/iso_data $DIR/decompiler_out
$DIR/build/decompiler/decompiler $DIR/decompiler/config/jak1_ntsc_black_label.jsonc $DIR/iso_data $DIR/decompiler_out
13 changes: 7 additions & 6 deletions decompiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ add_executable(decompiler
util/FileIO.cpp
config.cpp
util/LispPrint.cpp
util/DecompilerTypeSystem.cpp
Function/BasicBlocks.cpp
Disasm/InstructionMatching.cpp
TypeSystem/GoalType.cpp
TypeSystem/GoalFunction.cpp
TypeSystem/GoalSymbol.cpp
TypeSystem/TypeInfo.cpp
TypeSystem/TypeSpec.cpp Function/CfgVtx.cpp Function/CfgVtx.h)
Function/CfgVtx.cpp Function/CfgVtx.h
IR/BasicOpBuilder.cpp
IR/IR.cpp)

target_link_libraries(decompiler
minilzo
common_util)
common_util
type_system
fmt)
6 changes: 6 additions & 0 deletions decompiler/Disasm/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ struct InstructionAtom {
std::string to_string(const LinkedObjectFile& file) const;

bool is_link_or_label() const;
bool is_reg() const { return kind == REGISTER; }
bool is_imm() const { return kind == IMM; }
bool is_label() const { return kind == LABEL; }
bool is_sym() const { return kind == IMM_SYM; }

bool is_reg(Register r) const { return kind == REGISTER && reg == r; }

private:
int32_t imm;
Expand Down
5 changes: 5 additions & 0 deletions decompiler/Disasm/InstructionMatching.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#pragma once

/*!
* @file InstructionMatching.h
* Utilities for checking if an instruction matches some criteria.
*/

#ifndef JAK_DISASSEMBLER_INSTRUCTIONMATCHING_H
#define JAK_DISASSEMBLER_INSTRUCTIONMATCHING_H

Expand Down
5 changes: 5 additions & 0 deletions decompiler/Disasm/OpcodeInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/*!
* @file OpcodeInfo.cpp
* Decoding info for each opcode.
*/

#include "OpcodeInfo.h"
#include <cassert>

Expand Down
5 changes: 0 additions & 5 deletions decompiler/Function/BasicBlocks.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#pragma once

#ifndef JAK_DISASSEMBLER_BASICBLOCKS_H
#define JAK_DISASSEMBLER_BASICBLOCKS_H

#include <vector>
#include <memory>

Expand All @@ -21,5 +18,3 @@ struct BasicBlock {
std::vector<BasicBlock> find_blocks_in_function(const LinkedObjectFile& file,
int seg,
const Function& func);

#endif // JAK_DISASSEMBLER_BASICBLOCKS_H
14 changes: 2 additions & 12 deletions decompiler/Function/CfgVtx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,6 @@ void ControlFlowGraph::flag_early_exit(const std::vector<BasicBlock>& blocks) {
* Build and resolve a Control Flow Graph as much as possible.
*/
std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file, int seg, Function& func) {
printf("build cfg : %s\n", func.guessed_name.to_string().c_str());
auto cfg = std::make_shared<ControlFlowGraph>();

const auto& blocks = cfg->create_blocks(func.basic_blocks.size());
Expand Down Expand Up @@ -1716,25 +1715,16 @@ std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file, int se

cfg->flag_early_exit(func.basic_blocks);

// if(func.guessed_name.to_string() == "(method 9 thread)")
// cfg->find_cond_w_else();

// if (func.guessed_name.to_string() != "looping-code") {
// return cfg;
// }

bool changed = true;
while (changed) {
changed = false;
// note - we should prioritize finding short-circuiting expressions.
// printf("%s\n", cfg->to_dot().c_str());
// printf("%s\n", cfg->to_form()->toStringPretty().c_str());

changed = changed | cfg->find_cond_w_else();
changed = changed | cfg->find_cond_n_else();
changed = changed || cfg->find_cond_w_else();
changed = changed || cfg->find_cond_n_else();
changed = changed || cfg->find_while_loop_top_level();
// //// printf("while loops? %d\n", changed);
//// changed = changed || cfg->find_if_else_top_level();
changed = changed || cfg->find_seq_top_level();
changed = changed || cfg->find_short_circuits();

Expand Down
45 changes: 42 additions & 3 deletions decompiler/Function/Function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Function.h"
#include "decompiler/Disasm/InstructionMatching.h"
#include "decompiler/ObjectFile/LinkedObjectFile.h"
#include "decompiler/TypeSystem/TypeInfo.h"
#include "decompiler/util/DecompilerTypeSystem.h"

namespace {
std::vector<Register> gpr_backups = {make_gpr(Reg::GP), make_gpr(Reg::S5), make_gpr(Reg::S4),
Expand Down Expand Up @@ -418,7 +418,7 @@ void Function::check_epilogue(const LinkedObjectFile& file) {
*
* Updates the guessed_name of the function and updates type_info
*/
void Function::find_global_function_defs(LinkedObjectFile& file) {
void Function::find_global_function_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts) {
int state = 0;
int label_id = -1;
Register reg;
Expand Down Expand Up @@ -457,7 +457,8 @@ void Function::find_global_function_defs(LinkedObjectFile& file) {
auto& func = file.get_function_at_label(label_id);
assert(func.guessed_name.empty());
func.guessed_name.set_as_global(name);
get_type_info().inform_symbol(name, TypeSpec("function"));
dts.add_symbol(name, "function");
;
// todo - inform function.
}

Expand Down Expand Up @@ -549,4 +550,42 @@ void Function::find_method_defs(LinkedObjectFile& file) {
}
}
}
}

void Function::add_basic_op(std::shared_ptr<IR> op, int start_instr, int end_instr) {
op->is_basic_op = true;
assert(end_instr > start_instr);

for (int i = start_instr; i < end_instr; i++) {
instruction_to_basic_op[i] = basic_ops.size();
}
basic_op_to_instruction[basic_ops.size()] = start_instr;
basic_ops.push_back(op);
}

bool Function::instr_starts_basic_op(int idx) {
auto op = instruction_to_basic_op.find(idx);
if (op != instruction_to_basic_op.end()) {
auto start_instr = basic_op_to_instruction.at(op->second);
return start_instr == idx;
}
return false;
}

IR* Function::get_basic_op_at_instr(int idx) {
return basic_ops.at(instruction_to_basic_op.at(idx)).get();
}

int Function::get_basic_op_count() {
return basic_ops.size();
}

int Function::get_failed_basic_op_count() {
int count = 0;
for (auto& x : basic_ops) {
if (dynamic_cast<IR_Failed*>(x.get())) {
count++;
}
}
return count;
}
14 changes: 13 additions & 1 deletion decompiler/Function/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "decompiler/Disasm/Instruction.h"
#include "BasicBlocks.h"
#include "CfgVtx.h"
#include "decompiler/IR/IR.h"

class DecompilerTypeSystem;

struct FunctionName {
enum class FunctionKind {
Expand Down Expand Up @@ -60,8 +63,14 @@ class Function {
public:
Function(int _start_word, int _end_word);
void analyze_prologue(const LinkedObjectFile& file);
void find_global_function_defs(LinkedObjectFile& file);
void find_global_function_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts);
void find_method_defs(LinkedObjectFile& file);
void add_basic_op(std::shared_ptr<IR> op, int start_instr, int end_instr);
bool has_basic_ops() { return !basic_ops.empty(); }
bool instr_starts_basic_op(int idx);
IR* get_basic_op_at_instr(int idx);
int get_basic_op_count();
int get_failed_basic_op_count();

int segment = -1;
int start_word = -1;
Expand Down Expand Up @@ -115,6 +124,9 @@ class Function {

private:
void check_epilogue(const LinkedObjectFile& file);
std::vector<std::shared_ptr<IR>> basic_ops;
std::unordered_map<int, int> instruction_to_basic_op;
std::unordered_map<int, int> basic_op_to_instruction;
};

#endif // NEXT_FUNCTION_H
Loading