Skip to content

Commit

Permalink
Assembler: Error on unused labels
Browse files Browse the repository at this point in the history
  • Loading branch information
BenWiederhake committed Jun 23, 2023
1 parent 72b4f19 commit f3332db
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 6 deletions.
25 changes: 23 additions & 2 deletions assembler/asm.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ def __init__(self):
self.segment_words = [None] * (SEGMENT_LENGTH // 2)
self.current_lineno = None
self.current_pointer = 0x0000
self.known_labels = dict()
self.forward_references = dict()
self.unused_labels = set()
self.known_labels = dict() # Values are (destination_offset, destination_lineno)
self.forward_references = dict() # Values are lists of ForwardReference instances
self.error_log = []
self.expect_hash = None # Or tuple (line, SHA256 hex)

Expand Down Expand Up @@ -158,6 +159,7 @@ def forward(self, by_words, label_name, bound_method, data):
fwd_ref = ForwardReference(self, by_words, bound_method, data)
if label_name in self.known_labels:
# Immediate resolution
self.unused_labels.discard(label_name)
return fwd_ref.apply()
else:
# Must be skipped for now, to be patched when 'label_name' is defined
Expand Down Expand Up @@ -720,6 +722,7 @@ def emit_b_by_value(self, command, condition_reg, offset_value):

def emit_b_to_label(self, command, condition_reg, label_name):
destination_offset, destination_lineno = self.known_labels[label_name]
self.unused_labels.discard(label_name)
offset_value = mod_s16(destination_offset - self.current_pointer)
return self.emit_b_by_value(
f"{command} (to label {label_name}=0x{destination_offset:04X}, defined in line {destination_lineno})",
Expand Down Expand Up @@ -801,6 +804,7 @@ def command_j_immediate(self, command, offset):

def emit_j_to_label(self, label_name, extra_offset):
destination = self.known_labels[label_name][0] + extra_offset
self.unused_labels.discard(label_name)
delta = mod_s16(destination - self.current_pointer)
pseudo_command = f"j (to {label_name} {extra_offset:+} = by {delta:+})"
return self.command_j_immediate(pseudo_command, delta)
Expand Down Expand Up @@ -889,6 +893,7 @@ def parse_directive_offset(self, command, args):
f"The already-defined labels are: {sorted(list(self.known_labels.keys()))}"
)
self.current_pointer = self.known_labels[label_name][0]
self.unused_labels.discard(label_name)
# No codegen
return True

Expand Down Expand Up @@ -929,6 +934,7 @@ def parse_directive_label(self, command, args):
return self.error(
f"Label '{label_name}' previously defined in line {old_line} (old offset 0x{old_offset:04X}, new offset 0x{self.current_pointer:04X})"
)
assert label_name not in self.unused_labels
self.known_labels[label_name] = (self.current_pointer, self.current_lineno)
old_references = self.forward_references.get(label_name)
if old_references is not None:
Expand All @@ -939,6 +945,8 @@ def parse_directive_label(self, command, args):
any_reference_failed = True
if any_reference_failed:
return self.error(f"When label {label_name} was defined.")
else:
self.unused_labels.add(label_name)
# No codegen
return True

Expand Down Expand Up @@ -982,6 +990,7 @@ def parse_line(self, line, lineno):

def segment_bytes(self):
assert len(self.segment_words) == 65536
has_problem = False
if self.forward_references:
error_text = ", ".join(
f"line {fwd_ref.orig_lineno} at offset {fwd_ref.orig_pointer} references label {label_name}"
Expand All @@ -994,6 +1003,18 @@ def segment_bytes(self):
self.error(
f"Did you mean any of these defined labels? {list(self.known_labels.keys())}"
)
has_problem = True
if self.unused_labels:
error_text = ", ".join(
f"'{label_name}' (line {label_lineno}, offset {label_offset})"
for label_name in sorted(self.unused_labels)
for label_offset, label_lineno in [self.known_labels[label_name]]
)
# FIXME write test
self.error(
f"Unused label(s), try using them in dead code, or commenting them out: {error_text}"
)
if has_problem:
return None
segment = bytearray(SEGMENT_LENGTH)
for i, word in enumerate(self.segment_words):
Expand Down
12 changes: 10 additions & 2 deletions assembler/asm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,8 @@ def test_wrapping(self):
"""\
.label _hello_world
ret
# Cannot have an unreferenced label, sadly :(
.offset _hello_world
""",
"102A",
[],
Expand All @@ -782,6 +784,10 @@ def test_wrapping(self):
ret
.label _hello_more_world
lw r4, 0x56
# Cannot have an unreferenced label, sadly :(
.offset _hello_world
.offset _hello_world_again
.offset _hello_more_world
""",
"102A 3456",
[],
Expand Down Expand Up @@ -2175,6 +2181,7 @@ def test_wrapping(self):
[
"line 5: Found end of asm text, but some forward references are unresolved: line 4 at offset 2 references label _wrong_label",
"line 5: Did you mean any of these defined labels? ['_some_label']",
"line 5: Unused label(s), try using them in dead code, or commenting them out: '_some_label' (line 2, offset 1)",
],
),
(
Expand Down Expand Up @@ -2279,6 +2286,7 @@ def test_wrapping(self):
[
"line 5: Found end of asm text, but some forward references are unresolved: line 4 at offset 2 references label _wrong_label",
"line 5: Did you mean any of these defined labels? ['_some_label']",
"line 5: Unused label(s), try using them in dead code, or commenting them out: '_some_label' (line 2, offset 1)",
],
),
(
Expand Down Expand Up @@ -2893,14 +2901,14 @@ def test_wrapping(self):
lw r1, 0xFF89
lw r1, r1
b r1 _move_nonzero # (offset is +0x3)
.label _move_zero # On move 0, play in column 3.
# .label _move_zero # On move 0, play in column 3.
lw r0, 3
ret
.label _move_nonzero
lw r0, 18
ge r1 r0
b r0 _move_late # (offset is +0x2)
.label _move_early # On moves 1-17, play in column (n - 1) % 7.
# .label _move_early # On moves 1-17, play in column (n - 1) % 7.
decr r1
# j _move_late # Surprise optimization: This is a noop, this time!
.label _move_late # On moves 18-20, play in column n % 7.
Expand Down
4 changes: 2 additions & 2 deletions src/connect4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,14 +982,14 @@ mod test_game {
instructions_two[0] = 0x3189; // lw r1, 0xFF89
instructions_two[1] = 0x2111; // lw r1, r1
instructions_two[2] = 0x9101; // b r1 _move_nonzero # (offset is +0x3)
// .label _move_zero # On move 0, play in column 3.
// # .label _move_zero # On move 0, play in column 3.
instructions_two[3] = 0x3003; // lw r0, 3
instructions_two[4] = 0x102A; // ret
// .label _move_nonzero
instructions_two[5] = 0x3012; // lw r0, 18
instructions_two[6] = 0x8610; // ge r1 r0
instructions_two[7] = 0x9000; // b r0 _move_late # (offset is +0x2)
// .label _move_early # On moves 1-17, play in column (n - 1) % 7.
// # .label _move_early # On moves 1-17, play in column (n - 1) % 7.
instructions_two[8] = 0x5811; // decr r1
// # j _move_late # Surprise optimization: This is a noop, this time!
// .label _move_late # On moves 18-20, play in column n % 7.
Expand Down

0 comments on commit f3332db

Please sign in to comment.