summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2025-02-01 18:14:31 +0300
committerOxore <oxore@protonmail.com>2025-02-01 18:21:52 +0300
commitbea4c5538e287cd3b5943c1e45e8b24c5b462cb4 (patch)
treedcbd39477f9482006aa566d315c9d25026b90e1e /src/main.cpp
parent07ff2ebf9b29084670fb3fa46f8427d3272117d5 (diff)
Turn ReferenceRecord chains into a simple linked list
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp122
1 files changed, 59 insertions, 63 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 338b92b..2a060df 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -78,11 +78,9 @@ static constexpr bool ShouldPrintAsRaw(const Op& op)
static constexpr bool HasCallReference(const DisasmNode &node)
{
- for (const ReferenceNode *ref{node.ref_by}; ref; ref = ref->next) {
- for (size_t i = 0; i < ref->refs_count; i++) {
- if (ref->refs[i].type == ReferenceType::kCall) {
- return true;
- }
+ for (const ReferenceRecord *ref{node.ref_by}; ref; ref = ref->next) {
+ if (ref->type == ReferenceType::kCall) {
+ return true;
}
}
return false;
@@ -99,49 +97,46 @@ static constexpr size_t GetNodeSizeByAddress(const DisasmMap &disasm_map, const
static constexpr bool IsLocalLocation(const DisasmMap &disasm_map, const DisasmNode &node)
{
- for (const ReferenceNode *ref{node.ref_by}; ref; ref = ref->next) {
- for (size_t i = 0; i < ref->refs_count; i++) {
- // Check symtab, because we may be crossing a symbol
- const DisasmNode *ref_node = disasm_map.FindNodeByAddress(ref->refs[i].address);
- if (ref_node != nullptr) {
- // We won't cross a symbol at the address if the reference is
- // backwards ('1b') and we will cross a symbol if the reference
- // is forwards ('1f') - that's why we shift the range one
- // instruction forward by adding a size to the address and the
- // length.
- // TODO write tests for it
- uint32_t const address = (node.address < ref_node->address)
- ? node.address + node.size
- : ref_node->address + ref_node->size;
- size_t const length = (node.address < ref_node->address)
- ? ref_node->address + ref_node->size - (node.address + node.size)
- : node.address + node.size - (ref_node->address + ref_node->size);
- if (disasm_map.HasSymbolsInRange(address, length)) {
- return false;
- }
- }
- const ReferenceRecord &ref_rec = ref->refs[i];
- if (ref_rec.type == ReferenceType::kCall) {
- // Locals are definitely not made for calls
+ for (const ReferenceRecord *ref{node.ref_by}; ref; ref = ref->next) {
+ // Check symtab, because we may be crossing a symbol
+ const DisasmNode *ref_node = disasm_map.FindNodeByAddress(ref->address);
+ if (ref_node != nullptr) {
+ // We won't cross a symbol at the address if the reference is
+ // backwards ('1b') and we will cross a symbol if the reference
+ // is forwards ('1f') - that's why we shift the range one
+ // instruction forward by adding a size to the address and the
+ // length.
+ // TODO write tests for it
+ uint32_t const address = (node.address < ref_node->address)
+ ? node.address + node.size
+ : ref_node->address + ref_node->size;
+ size_t const length = (node.address < ref_node->address)
+ ? ref_node->address + ref_node->size - (node.address + node.size)
+ : node.address + node.size - (ref_node->address + ref_node->size);
+ if (disasm_map.HasSymbolsInRange(address, length)) {
return false;
}
- const bool forward = ref_rec.address < node.address;
- const size_t min_addr = forward ? ref_rec.address : node.address;
- const size_t start = min_addr + GetNodeSizeByAddress(disasm_map, min_addr);
- const size_t max_addr = forward ? node.address : ref_rec.address;
- const size_t end = max_addr + (forward ? 0 : GetNodeSizeByAddress(disasm_map, min_addr));
- for (size_t addr = start; addr < end;) {
- const auto *intermediate_node = disasm_map.FindNodeByAddress(addr);
- if (intermediate_node) {
- if (intermediate_node->ref_by) {
- // Another labeled node detected on the jump path, hence
- // current node's location cannot be considered local
- return false;
- }
- addr += intermediate_node->size;
- } else {
- addr += kInstructionSizeStepBytes;
+ }
+ if (ref->type == ReferenceType::kCall) {
+ // Locals are definitely not made for calls
+ return false;
+ }
+ const bool forward = ref->address < node.address;
+ const size_t min_addr = forward ? ref->address : node.address;
+ const size_t start = min_addr + GetNodeSizeByAddress(disasm_map, min_addr);
+ const size_t max_addr = forward ? node.address : ref->address;
+ const size_t end = max_addr + (forward ? 0 : GetNodeSizeByAddress(disasm_map, min_addr));
+ for (size_t addr = start; addr < end;) {
+ const auto *intermediate_node = disasm_map.FindNodeByAddress(addr);
+ if (intermediate_node) {
+ if (intermediate_node->ref_by) {
+ // Another labeled node detected on the jump path, hence
+ // current node's location cannot be considered local
+ return false;
}
+ addr += intermediate_node->size;
+ } else {
+ addr += kInstructionSizeStepBytes;
}
}
}
@@ -329,6 +324,11 @@ struct EmitContext {
size_t last_rendered_function_symbol_addr{SIZE_MAX};
};
+static constexpr const char *commentSequence(const Settings &s)
+{
+ return s.target_asm == TargetAssembler::kGnuAs ? "|" : ";";
+}
+
static bool EmitNodeDisassembly(
const EmitContext &ctx,
const DisasmMap &disasm_map,
@@ -363,8 +363,7 @@ static bool EmitNodeDisassembly(
if (s.labels && !is_local) {
const bool export_this_function = s.export_functions && have_call_reference;
const bool export_this_label = s.export_all_labels ||
- (s.export_labels && node.ref_by && (node.ref_by->refs_count > 1)) ||
- export_this_function;
+ (s.export_labels && node.ref_by) || export_this_function;
if (export_this_label) {
fprintf(output, "\n%s.globl\t%s\n", s.indent, name);
if (export_this_function) {
@@ -382,24 +381,21 @@ static bool EmitNodeDisassembly(
}
} while (0);
if (s.xrefs_from && (have_symbol || !is_local)) {
- if (s.target_asm == TargetAssembler::kGnuAs) {
- fprintf(output, "| XREFS:\n");
- } else {
- fprintf(output, "; XREFS:\n");
- }
- for (const ReferenceNode *ref{node.ref_by}; ref; ref = ref->next) {
- if (ref->refs_count == 0) {
- continue;
+ assert(s.xrefs_per_line >= 1);
+ fprintf(output, "%s XREFS:\n", commentSequence(s));
+ size_t refs_count = 0;
+ for (const ReferenceRecord *ref{node.ref_by}; ref; ref = ref->next) {
+ if (refs_count == 0) {
+ fprintf(output, commentSequence(s));
}
- if (s.target_asm == TargetAssembler::kGnuAs) {
- fprintf(output, "|");
- } else {
- fprintf(output, ";");
- }
- for (size_t i = 0; i < ref->refs_count; i++) {
- const ReferenceRecord r = ref->refs[i];
- fprintf(output, " %s @%08x", ReferenceTypeToString(r.type), r.address);
+ fprintf(output, " %s @%08x", ReferenceTypeToString(ref->type), ref->address);
+ refs_count++;
+ if (refs_count >= s.xrefs_per_line) {
+ fprintf(output, "\n");
+ refs_count = 0;
}
+ }
+ if (refs_count != 0) {
fprintf(output, "\n");
}
}