summaryrefslogtreecommitdiff
path: root/src
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
parent07ff2ebf9b29084670fb3fa46f8427d3272117d5 (diff)
Turn ReferenceRecord chains into a simple linked list
Diffstat (limited to 'src')
-rw-r--r--src/common.h1
-rw-r--r--src/disasm.cpp23
-rw-r--r--src/disasm.h13
-rw-r--r--src/main.cpp122
4 files changed, 71 insertions, 88 deletions
diff --git a/src/common.h b/src/common.h
index 7b91847..40be645 100644
--- a/src/common.h
+++ b/src/common.h
@@ -50,6 +50,7 @@ struct Settings {
const char *output_dir_path{};
SplitParams split{};
TargetAssembler target_asm{};
+ size_t xrefs_per_line{5};
};
using RefKindMask = unsigned;
diff --git a/src/disasm.cpp b/src/disasm.cpp
index a7dc07b..35c2351 100644
--- a/src/disasm.cpp
+++ b/src/disasm.cpp
@@ -11,29 +11,22 @@
void DisasmNode::AddReferencedBy(const uint32_t address_from, const ReferenceType ref_type)
{
- ReferenceNode *node{};
+ ReferenceRecord *node = new ReferenceRecord{nullptr, ref_type, address_from};
+ assert(node);
if (this->last_ref_by) {
- node = this->last_ref_by;
+ this->last_ref_by->next = node;
} else {
- node = new ReferenceNode{};
- assert(node);
- this->ref_by = this->last_ref_by = node;
- }
- node->refs[node->refs_count] = ReferenceRecord{ref_type, address_from};
- node->refs_count++;
- if (node->refs_count >= kRefsCountPerBuffer) {
- ReferenceNode *new_node = new ReferenceNode{};
- assert(new_node);
- node->next = new_node;
- this->last_ref_by = new_node;
+ assert(nullptr == this->ref_by);
+ this->ref_by = node;
}
+ this->last_ref_by = node;
}
DisasmNode::~DisasmNode()
{
- ReferenceNode *ref{this->ref_by};
+ ReferenceRecord *ref{this->ref_by};
while (ref) {
- ReferenceNode *prev = ref;
+ ReferenceRecord *prev = ref;
ref = ref->next;
delete prev;
}
diff --git a/src/disasm.h b/src/disasm.h
index 5b1b4b9..2a6a1d0 100644
--- a/src/disasm.h
+++ b/src/disasm.h
@@ -20,18 +20,11 @@ enum class ReferenceType {
};
struct ReferenceRecord {
+ ReferenceRecord *next{};
ReferenceType type{};
uint32_t address{};
};
-constexpr size_t kRefsCountPerBuffer = 10;
-
-struct ReferenceNode {
- ReferenceNode *next{};
- ReferenceRecord refs[kRefsCountPerBuffer];
- uint32_t refs_count{};
-};
-
enum class NodeType {
kTracedInstruction,
kRefInstruction,
@@ -50,8 +43,8 @@ struct DisasmNode {
uint32_t ref1_addr{};
/// Address of second argument reference
uint32_t ref2_addr{};
- ReferenceNode *ref_by{};
- ReferenceNode *last_ref_by{};
+ ReferenceRecord *ref_by{};
+ ReferenceRecord *last_ref_by{};
Op op{};
/*! Disassembles instruction with arguments
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");
}
}