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

[decomp] finish actor-link-h and a few more #592

Merged
merged 3 commits into from
Jun 15, 2021
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ Run tests:
./test.sh
```

Note: we have found that `clang` and `lld` are significantly faster to compile and link than `gcc`, generate faster code, and have better warning messages. To install these:
```
sudo apt install lld clang
```
and run `cmake` (in a fresh build directory) with:
```
cmake -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
```
this decreases the compile and link time from ~10 seconds to ~4 seconds.

## Getting Started - Linux (Arch)

Install packages and init repository:
Expand Down
18 changes: 12 additions & 6 deletions decompiler/IR2/Env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,12 +417,12 @@ std::vector<VariableNames::VarInfo> Env::extract_visible_variables(
return entries;
}

goos::Object Env::local_var_type_list(const Form* top_level_form,
int nargs_to_ignore,
int* count_out) const {
FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
int nargs_to_ignore) const {
assert(nargs_to_ignore <= 8);
auto vars = extract_visible_variables(top_level_form);

FunctionVariableDefinitions result;
std::vector<goos::Object> elts;
elts.push_back(pretty_print::to_symbol("local-vars"));
int count = 0;
Expand All @@ -432,6 +432,11 @@ goos::Object Env::local_var_type_list(const Form* top_level_form,
continue;
}

if (x.reg_id.reg == Register(Reg::GPR, Reg::S6)) {
result.had_pp = true;
continue;
}

std::string lookup_name = x.name();
auto remapped = m_var_remap.find(lookup_name);
if (remapped != m_var_remap.end()) {
Expand Down Expand Up @@ -459,10 +464,11 @@ goos::Object Env::local_var_type_list(const Form* top_level_form,
count++;
}

if (count_out) {
*count_out = count;
result.count = count;
if (count > 0) {
result.local_vars = pretty_print::build_list(elts);
}
return pretty_print::build_list(elts);
return result;
}

std::unordered_set<RegId, RegId::hash> Env::get_ssa_var(const RegAccessSet& vars) const {
Expand Down
11 changes: 8 additions & 3 deletions decompiler/IR2/Env.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ struct StackSpillEntry {
}
};

struct FunctionVariableDefinitions {
std::optional<goos::Object> local_vars;
bool had_pp = false;
int count = 0;
};

/*!
* An "environment" for a single function.
* This contains data for an entire function, like which registers are live when, the types of
Expand Down Expand Up @@ -122,9 +128,8 @@ class Env {

std::vector<VariableNames::VarInfo> extract_visible_variables(const Form* top_level_form) const;
std::string print_local_var_types(const Form* top_level_form) const;
goos::Object local_var_type_list(const Form* top_level_form,
int nargs_to_ignore,
int* count_out) const;
FunctionVariableDefinitions local_var_type_list(const Form* top_level_form,
int nargs_to_ignore) const;

std::unordered_set<RegId, RegId::hash> get_ssa_var(const RegAccessSet& vars) const;
RegId get_program_var_id(const RegisterAccess& var) const;
Expand Down
3 changes: 2 additions & 1 deletion decompiler/IR2/Form.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,8 @@ goos::Object SetVarElement::to_form_internal(const Env& env) const {
}
}

return pretty_print::build_list("set!", m_dst.to_form(env), m_src->to_form(env));
return pretty_print::build_list(
"set!", m_dst.to_form(env, RegisterAccess::Print::AS_VARIABLE_NO_CAST), m_src->to_form(env));
}

std::optional<TypeSpec> SetVarElement::required_cast(const Env& env) const {
Expand Down
1 change: 0 additions & 1 deletion decompiler/ObjectFile/ObjectFileDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ void ObjectFileDB::load_map_file(const std::string& map_data) {
}
}

constexpr int MAX_CHUNK_SIZE = 0x8000;
/*!
* Load the objects stored in the given DGO into the ObjectFileDB
*/
Expand Down
2 changes: 1 addition & 1 deletion decompiler/ObjectFile/ObjectFileDB_IR2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ void ObjectFileDB::ir2_cfg_build_pass() {
try {
build_initial_forms(func);
} catch (std::exception& e) {
func.warnings.general_warning("Failed to structure");
func.warnings.general_warning("Failed to structure: {}", e.what());
func.ir2.top_form = nullptr;
}
}
Expand Down
55 changes: 29 additions & 26 deletions decompiler/analysis/final_output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ goos::Object get_arg_list_for_function(const Function& func, const Env& env) {
return pretty_print::build_list(argument_elts);
}

namespace {
void append_to_body(goos::Object* top_form,
const std::vector<goos::Object>& inline_body,
const FunctionVariableDefinitions& var_dec) {
if (var_dec.local_vars) {
pretty_print::append(*top_form, pretty_print::build_list(*var_dec.local_vars));
}

if (var_dec.had_pp) {
std::vector<goos::Object> body_with_pp;
body_with_pp.push_back(pretty_print::to_symbol("with-pp"));
body_with_pp.insert(body_with_pp.end(), inline_body.begin(), inline_body.end());
pretty_print::append(*top_form,
pretty_print::build_list(pretty_print::build_list(body_with_pp)));
} else {
pretty_print::append(*top_form, pretty_print::build_list(inline_body));
}
}
} // namespace

std::string final_defun_out(const Function& func,
const Env& env,
const DecompilerTypeSystem& dts,
Expand All @@ -31,8 +51,8 @@ std::string final_defun_out(const Function& func,
return e.what();
}

int var_count = 0;
auto var_dec = env.local_var_type_list(func.ir2.top_form, func.type.arg_count() - 1, &var_count);
// int var_count = 0;
auto var_dec = env.local_var_type_list(func.ir2.top_form, func.type.arg_count() - 1);
auto arguments = get_arg_list_for_function(func, env);

if (func.guessed_name.kind == FunctionName::FunctionKind::GLOBAL) {
Expand All @@ -48,11 +68,7 @@ std::string final_defun_out(const Function& func,
top.push_back(arguments);
auto top_form = pretty_print::build_list(top);

if (var_count > 0) {
append(top_form, pretty_print::build_list(var_dec));
}

append(top_form, pretty_print::build_list(inline_body));
append_to_body(&top_form, inline_body, var_dec);
return pretty_print::to_string(top_form);
}

Expand All @@ -67,11 +83,7 @@ std::string final_defun_out(const Function& func,
top.push_back(arguments);
auto top_form = pretty_print::build_list(top);

if (var_count > 0) {
append(top_form, pretty_print::build_list(var_dec));
}

append(top_form, pretty_print::build_list(inline_body));
append_to_body(&top_form, inline_body, var_dec);
return pretty_print::to_string(top_form);
}

Expand All @@ -82,11 +94,7 @@ std::string final_defun_out(const Function& func,
top.push_back(arguments);
auto top_form = pretty_print::build_list(top);

if (var_count > 0) {
append(top_form, pretty_print::build_list(var_dec));
}

append(top_form, pretty_print::build_list(inline_body));
append_to_body(&top_form, inline_body, var_dec);
return pretty_print::to_string(top_form);
}

Expand All @@ -99,11 +107,7 @@ std::string final_defun_out(const Function& func,
top.push_back(arguments);
auto top_form = pretty_print::build_list(top);

if (var_count > 0) {
append(top_form, pretty_print::build_list(var_dec));
}

append(top_form, pretty_print::build_list(inline_body));
append_to_body(&top_form, inline_body, var_dec);
return pretty_print::to_string(top_form);
}
return "nyi";
Expand Down Expand Up @@ -194,10 +198,9 @@ std::string write_from_top_level(const Function& top_level,

std::string result;
// local vars:
int var_count = 0;
auto var_dec = env.local_var_type_list(top_level.ir2.top_form, 0, &var_count);
if (var_count > 0) {
result += pretty_print::to_string(var_dec);
auto var_dec = env.local_var_type_list(top_level.ir2.top_form, 0);
if (var_dec.local_vars) {
result += pretty_print::to_string(*var_dec.local_vars);
result += '\n';
result += '\n';
}
Expand Down
Loading