rexcode/isa: display-side label naming — address order, offset-keyed names

Internal label ids are allocation-order handles: the encoder's creation
order, or the decoder's branch-DISCOVERY order (a loop's latch names the
header before an earlier forward target). Printing labels by raw id leaked
that accident into listings — label numbers appeared out of order down the
page — and the printers' `label_names: ^map[u32]string` keyed the caller's
names by those synthesized ids, which a decode consumer cannot know without
re-deriving them (the practical result: naming "label 0" could caption a
random interior branch target).

Naming is now derived at the presentation seam, shared by every ISA
(`isa.Label_Display` in isa/print.odin):

  - display numbers are assigned in ASCENDING ADDRESS order, so a listing
    reads L0, L1, L2 … top to bottom regardless of id allocation;
  - caller names are keyed by BYTE OFFSET (`isa.Label_Names`, with a
    `distinct` Label_Offset key so an id-keyed map from the old contract
    fails to compile instead of silently mis-naming);
  - a named offset is guaranteed a label row even when no Label_Definition
    points at it — `names[0] = "factorial"` heads a function's listing.

All ten ISA printers (x86, mips, rsp, arm32, arm64, riscv, ppc, ppc_vle,
mos6502, mos65816) drop their per-printer offset_to_label maps and
write_label helpers for the shared display; each arch re-exports
Label_Offset/Label_Names beside Label_Definition. En route this fixes an
arm32/ppc/ppc_vle bug where passing ANY names map suppressed the default
L<n> label rows for unnamed labels. Decode-side id assignment is untouched:
the reloc round-trip contract (encoder ids surviving decode) and the
sparse-id padding it relies on stay exactly as they were.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Riok9vMpkLmo78wsVKJHhz
This commit is contained in:
Flāvius
2026-08-03 20:51:55 -04:00
parent da15373ee9
commit 2e8d3b9e10
25 changed files with 424 additions and 477 deletions

View File

@@ -142,9 +142,9 @@ x86.label_set(&lm, "done", &instructions)
result := x86.encode(instructions[:], lm.labels[:], code[:], &relocs, &errors)
// Printer wants idname; Label_Map stores nameid, so invert once.
id_to_name := make(map[u32]string, len(lm.names), context.temp_allocator)
for name, id in lm.names { id_to_name[id] = name }
x86.print(decoded_insts[:], decoded_info[:], lm.labels[:], label_names = &id_to_name)
names := make(x86.Label_Names, len(lm.names), context.temp_allocator) // BYTE OFFSET -> name
for name, id in lm.names { names[x86.Label_Offset(u32(lm.labels[id]))] = name }
x86.print(decoded_insts[:], decoded_info[:], lm.labels[:], label_names = &names)
```
## Driver script (`build.lua`)

View File

@@ -54,6 +54,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -70,7 +70,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -78,13 +78,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -93,16 +91,10 @@ sbprint :: proc(
offset = inst_info[i].offset
}
// Label preceding this instruction (if any)
if id, ok := offset_to_label[offset]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
strings.write_string(sb, ":\n")
}
} else {
fmt.sbprintf(sb, "L%d:\n", id)
}
// A displayable label at this offset — a definition, or a caller-named offset
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_string(sb, ":\n")
}
if opts.show_offsets {
@@ -138,7 +130,7 @@ sbprint :: proc(
strings.write_string(sb, " ")
for k in 0..<inst.operand_count {
if k > 0 { strings.write_string(sb, ", ") }
write_operand(sb, &inst.ops[k], inst, offset, &offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[k], inst, offset, &display, opts)
}
}
strings.write_string(sb, "\n")
@@ -269,7 +261,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -281,7 +273,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -290,7 +282,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -299,7 +291,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -309,7 +301,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -319,7 +311,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -328,7 +320,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -338,7 +330,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -348,7 +340,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -358,7 +350,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -368,7 +360,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -378,7 +370,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -388,7 +380,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -460,8 +452,7 @@ write_operand :: proc(
op: ^Operand,
inst: ^Instruction,
offset: u32,
offset_to_label: ^map[u32]u32,
label_names: ^map[u32]string,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
@@ -482,14 +473,8 @@ write_operand :: proc(
case .RELATIVE:
// Resolve to label if possible
target := u32(i64(offset) + op.relative)
if id, ok := offset_to_label[target]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
return
}
}
fmt.sbprintf(sb, "L%d", id)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
// raw absolute
fmt.sbprintf(sb, "0x%x", target)

View File

@@ -40,6 +40,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -79,7 +79,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -87,13 +87,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -102,8 +100,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -130,7 +129,7 @@ sbprint :: proc(
strings.write_byte(sb, ',')
if opts.space_after_comma { strings.write_byte(sb, ' ') }
}
write_operand(sb, &inst.ops[slot], offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], &display, opts)
}
}
strings.write_string(sb, opts.separator)
@@ -144,7 +143,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -156,7 +155,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -165,7 +164,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -174,7 +173,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -184,7 +183,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -194,7 +193,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -203,7 +202,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -213,7 +212,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -223,7 +222,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -233,7 +232,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -243,7 +242,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -253,7 +252,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -263,7 +262,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -390,11 +389,10 @@ write_register :: proc(sb: ^strings.Builder, r: Register, uppercase: bool) {
@(private="file")
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
sb: ^strings.Builder,
op: ^Operand,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -449,8 +447,8 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
isa.print_hex(sb, u64(target), opts)
}
@@ -512,23 +510,6 @@ write_memory :: proc(sb: ^strings.Builder, m: Memory, opts: ^Print_Options) {
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 { strings.write_byte(sb, '0'); return }

View File

@@ -38,6 +38,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map
// Relocation and Relocation_Type live in reloc.odin (per-arch by design).

View File

@@ -74,7 +74,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -83,14 +83,11 @@ sbprint :: proc(
opts = &defaults
}
// Offset -> label_id index (single linear pass over label_defs).
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -99,9 +96,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
// Label at this offset?
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -123,7 +120,7 @@ sbprint :: proc(
strings.write_byte(sb, ' ')
}
}
write_operand(sb, &inst.ops[slot], offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], &display, opts)
}
}
strings.write_string(sb, opts.separator)
@@ -137,7 +134,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -153,7 +150,7 @@ print :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -166,7 +163,7 @@ println :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -179,7 +176,7 @@ aprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -193,7 +190,7 @@ aprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -207,7 +204,7 @@ tprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -220,7 +217,7 @@ tprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -234,7 +231,7 @@ bprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -248,7 +245,7 @@ bprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -262,7 +259,7 @@ fprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -276,7 +273,7 @@ fprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -290,7 +287,7 @@ wprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -304,7 +301,7 @@ wprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -404,11 +401,10 @@ write_register :: proc(sb: ^strings.Builder, r: Register, uppercase: bool) {
@(private="file")
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
sb: ^strings.Builder,
op: ^Operand,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -428,8 +424,8 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
// No label discovered at this target -- fall back to absolute hex.
isa.print_hex(sb, u64(target), opts)
@@ -437,23 +433,6 @@ write_operand :: proc(
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 {

View File

@@ -173,9 +173,9 @@ run_printer_tests :: proc() {
clear(&errors)
mips.decode(code[:byte_count], nil, &dec_insts, &dec_info, &dec_labels, &errors)
names: map[u32]string
names: mips.Label_Names // keyed by BYTE OFFSET
defer delete(names)
names[0] = "loop"
names[mips.Label_Offset(0)] = "loop"
out := mips.aprint(dec_insts[:], dec_info[:], dec_labels[:],
nil, nil, &names, context.temp_allocator)
pcheck("Named label",

View File

@@ -30,6 +30,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map
// Relocation and Relocation_Type live in reloc.odin (per-arch by design).

View File

@@ -61,7 +61,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -69,13 +69,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -84,8 +82,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -107,7 +106,7 @@ sbprint :: proc(
strings.write_byte(sb, ' ')
}
}
write_operand(sb, &inst.ops[slot], offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], &display, opts)
}
}
strings.write_string(sb, opts.separator)
@@ -121,7 +120,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -133,7 +132,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -142,7 +141,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -151,7 +150,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -161,7 +160,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -171,7 +170,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -180,7 +179,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -190,7 +189,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -200,7 +199,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -210,7 +209,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -220,7 +219,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -230,7 +229,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -240,7 +239,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -277,9 +276,8 @@ write_mnemonic :: proc(sb: ^strings.Builder, m: Mnemonic, uppercase: bool) {
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -297,8 +295,8 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
// Fall back to absolute hex when the target isn't a known label.
// Use the operand size to decide width: size=1 -> $XX, size=2 -> $XXXX.
@@ -379,23 +377,6 @@ write_hex_value :: proc(sb: ^strings.Builder, v: u64, size: u8) {
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 { strings.write_byte(sb, '0'); return }

View File

@@ -248,9 +248,9 @@ run_pipeline_tests :: proc() {
m.decode(code[:byte_count], nil,
&d_insts, &d_info, &d_labels, &errors, cpu = .CMOS_65C02)
names: map[u32]string
names: m.Label_Names // keyed by BYTE OFFSET
defer delete(names)
names[0] = "start"
names[m.Label_Offset(0)] = "start"
text := m.aprint(d_insts[:], d_info[:], d_labels[:],
nil, nil, &names, context.temp_allocator)

View File

@@ -33,6 +33,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -60,7 +60,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -68,13 +68,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -83,8 +81,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -113,7 +112,7 @@ sbprint :: proc(
strings.write_byte(sb, '#')
write_hex_value(sb, u64(inst.ops[slot].immediate), 1)
} else {
write_operand(sb, &inst.ops[slot], offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], &display, opts)
}
}
}
@@ -128,7 +127,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -140,7 +139,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -149,7 +148,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -158,7 +157,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -168,7 +167,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -178,7 +177,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -187,7 +186,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -197,7 +196,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -207,7 +206,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -217,7 +216,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -227,7 +226,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -237,7 +236,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -247,7 +246,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -276,9 +275,8 @@ write_mnemonic :: proc(sb: ^strings.Builder, m: Mnemonic, uppercase: bool) {
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -295,8 +293,8 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
write_hex_value(sb, u64(target), op.size)
}
@@ -395,23 +393,6 @@ write_hex_value :: proc(sb: ^strings.Builder, v: u64, size: u8) {
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 { strings.write_byte(sb, '0'); return }

View File

@@ -70,6 +70,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -57,7 +57,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -65,13 +65,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -80,15 +78,10 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if id, ok := offset_to_label[offset]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
strings.write_string(sb, ":\n")
}
} else {
fmt.sbprintf(sb, "L%d:\n", id)
}
// A displayable label at this offset — a definition, or a caller-named offset
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_string(sb, ":\n")
}
if opts.show_offsets {
@@ -107,7 +100,7 @@ sbprint :: proc(
strings.write_string(sb, " ")
for k in 0..<inst.operand_count {
if k > 0 { strings.write_string(sb, ", ") }
write_operand(sb, &inst.ops[k], offset, &offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[k], offset, &display, opts)
}
}
strings.write_string(sb, "\n")
@@ -121,7 +114,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -137,7 +130,7 @@ print :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -150,7 +143,7 @@ println :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -163,7 +156,7 @@ aprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -177,7 +170,7 @@ aprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -191,7 +184,7 @@ tprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -204,7 +197,7 @@ tprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -218,7 +211,7 @@ bprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -232,7 +225,7 @@ bprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -246,7 +239,7 @@ fprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -260,7 +253,7 @@ fprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -274,7 +267,7 @@ wprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -288,7 +281,7 @@ wprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -361,9 +354,8 @@ write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
inst_offset: u32,
offset_to_label: ^map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
#partial switch op.kind {
case .NONE:
@@ -393,14 +385,8 @@ write_operand :: proc(
// (post-decode) or an absolute label target if a label_defs roundtrip
// has resolved it. Prefer label form when we can match the target.
target := u32(i32(inst_offset) + i32(op.relative))
if id, ok := offset_to_label[target]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
return
}
}
fmt.sbprintf(sb, "L%d", id)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
// Print as PC-relative offset
if op.relative >= 0 {

View File

@@ -20,6 +20,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -35,7 +35,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -43,13 +43,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -58,15 +56,10 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if id, ok := offset_to_label[offset]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
strings.write_string(sb, ":\n")
}
} else {
fmt.sbprintf(sb, "L%d:\n", id)
}
// A displayable label at this offset — a definition, or a caller-named offset
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_string(sb, ":\n")
}
if opts.show_offsets {
@@ -85,7 +78,7 @@ sbprint :: proc(
strings.write_string(sb, " ")
for k in 0..<inst.operand_count {
if k > 0 { strings.write_string(sb, ", ") }
write_operand(sb, &inst.ops[k], offset, &offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[k], offset, &display, opts)
}
}
strings.write_string(sb, "\n")
@@ -99,7 +92,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -115,7 +108,7 @@ print :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -128,7 +121,7 @@ println :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -141,7 +134,7 @@ aprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -155,7 +148,7 @@ aprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -169,7 +162,7 @@ tprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -182,7 +175,7 @@ tprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -196,7 +189,7 @@ bprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -210,7 +203,7 @@ bprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -224,7 +217,7 @@ fprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -238,7 +231,7 @@ fprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -252,7 +245,7 @@ wprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -266,7 +259,7 @@ wprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -369,9 +362,8 @@ write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
inst_offset: u32,
offset_to_label: ^map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
#partial switch op.kind {
case .NONE: // skip
@@ -389,14 +381,8 @@ write_operand :: proc(
}
case .RELATIVE:
target := u32(i32(inst_offset) + i32(op.relative))
if id, ok := offset_to_label[target]; ok {
if label_names != nil {
if name, has := label_names[id]; has {
strings.write_string(sb, name)
return
}
}
fmt.sbprintf(sb, "L%d", id)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
if op.relative >= 0 {
fmt.sbprintf(sb, ".+%d", op.relative)

View File

@@ -137,3 +137,111 @@ print_decimal :: proc(sb: ^strings.Builder, value: u32) {
strings.write_byte(sb, buf[j])
}
}
// -----------------------------------------------------------------------------
// Label display (presentation-side naming)
// -----------------------------------------------------------------------------
//
// Internal label ids are allocation-order handles — the encoder's creation
// order, or the decoder's branch-DISCOVERY order (a loop's latch names the
// header before an earlier forward target). That order is an accident as far
// as a listing is concerned: naming labels by raw id makes the numbers appear
// out of order down the page. Display naming is therefore derived HERE, once
// per print call, independent of the ids:
//
// - every DEFINED label offset gets a display number in ASCENDING ADDRESS
// order, so a listing reads L0, L1, L2 … top to bottom;
// - the caller may name any BYTE OFFSET via `Label_Names`
// (`names[0] = "factorial"` heads the listing with the function name) —
// a named offset is displayable even when no Label_Definition points at
// it, since nothing need branch to a function's entry.
//
// `Label_Offset` is a distinct type so a map keyed by the OLD contract
// (internal label ids) fails to compile instead of silently mis-naming.
Label_Offset :: distinct u32
// Caller-supplied display names, keyed by byte offset into the printed region.
Label_Names :: map[Label_Offset]string
// Per-print-call display state: the sorted set of displayable label offsets
// (display number = index) plus the caller's names.
Label_Display :: struct {
offsets: [dynamic]u32, // ascending; a label's display number is its index here
names: ^Label_Names, // byte-offset-keyed caller names (nil = none)
}
label_display_init :: proc(display: ^Label_Display, label_defs: []Label_Definition, names: ^Label_Names, allocator := context.allocator) {
display.names = names
display.offsets = make([dynamic]u32, 0, len(label_defs), allocator)
insert_sorted :: proc(offsets: ^[dynamic]u32, offset: u32) {
lo, hi := 0, len(offsets)
for lo < hi {
mid := (lo + hi) / 2
if offsets[mid] < offset {
lo = mid + 1
} else {
hi = mid
}
}
if lo < len(offsets) && offsets[lo] == offset {
return // already displayable
}
append(offsets, 0)
copy(offsets[lo + 1:], offsets[lo:])
offsets[lo] = offset
}
for definition in label_defs {
if definition == LABEL_UNDEFINED do continue
insert_sorted(&display.offsets, u32(definition))
}
if names != nil {
for offset in names^ {
insert_sorted(&display.offsets, u32(offset))
}
}
}
label_display_destroy :: proc(display: ^Label_Display) {
delete(display.offsets)
}
// Is there a displayable label at `offset` (a definition, or a caller-named offset)?
label_display_at :: proc(display: ^Label_Display, offset: u32) -> bool {
_, found := label_display_rank(display, offset)
return found
}
// The display number of the label at `offset` (its rank in address order).
label_display_rank :: proc(display: ^Label_Display, offset: u32) -> (rank: int, found: bool) {
lo, hi := 0, len(display.offsets)
for lo < hi {
mid := (lo + hi) / 2
if display.offsets[mid] < offset {
lo = mid + 1
} else {
hi = mid
}
}
if lo < len(display.offsets) && display.offsets[lo] == offset {
return lo, true
}
return 0, false
}
// Write the display name for the label at `offset`: the caller's name for that
// offset if one was supplied, else `<prefix><rank>` with the address-ordered rank.
label_display_write :: proc(display: ^Label_Display, sb: ^strings.Builder, offset: u32, prefix: string) {
if display.names != nil {
if name, has := display.names^[Label_Offset(offset)]; has {
strings.write_string(sb, name)
return
}
}
rank, found := label_display_rank(display, offset)
if !found {
rank = 0 // an undisplayable offset never reaches here from the printers; be lenient
}
strings.write_string(sb, prefix)
print_decimal(sb, u32(rank))
}

View File

@@ -34,6 +34,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map

View File

@@ -77,7 +77,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -85,13 +85,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -100,8 +98,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -121,7 +120,7 @@ sbprint :: proc(
strings.write_byte(sb, ',')
if opts.space_after_comma { strings.write_byte(sb, ' ') }
}
write_operand(sb, &inst.ops[slot], inst.mnemonic, offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], inst.mnemonic, &display, opts)
}
}
strings.write_string(sb, opts.separator)
@@ -135,7 +134,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -147,7 +146,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -156,7 +155,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -165,7 +164,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -175,7 +174,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -185,7 +184,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -194,7 +193,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -204,7 +203,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -214,7 +213,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -224,7 +223,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -234,7 +233,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -244,7 +243,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -254,7 +253,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -308,10 +307,9 @@ write_register :: proc(sb: ^strings.Builder, r: Register, uppercase: bool) {
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
mnemonic: Mnemonic,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
mnemonic: Mnemonic,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -335,31 +333,14 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
isa.print_hex(sb, u64(target), opts)
}
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 { strings.write_byte(sb, '0'); return }

View File

@@ -35,6 +35,8 @@ import "core:rexcode/isa"
Error :: isa.Error
Error_Code :: isa.Error_Code
Label_Definition :: isa.Label_Definition
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Map :: isa.Label_Map
// Relocation and Relocation_Type live in reloc.odin (per-arch by design).

View File

@@ -72,7 +72,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
opts := options
if opts == nil {
@@ -80,13 +80,11 @@ sbprint :: proc(
opts = &defaults
}
offset_to_label: map[u32]u32
defer delete(offset_to_label)
for ld, id in label_defs {
if ld != LABEL_UNDEFINED {
offset_to_label[u32(ld)] = u32(id)
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for i in 0..<len(instructions) {
inst := &instructions[i]
@@ -95,8 +93,9 @@ sbprint :: proc(
offset = inst_info[i].offset
}
if label_id, has := offset_to_label[offset]; has {
write_label(sb, label_id, label_names, opts)
// A displayable label at this offset — a definition, or a caller-named offset?
if isa.label_display_at(&display, offset) {
isa.label_display_write(&display, sb, offset, opts.label_prefix)
strings.write_byte(sb, ':')
strings.write_string(sb, opts.separator)
}
@@ -118,7 +117,7 @@ sbprint :: proc(
strings.write_byte(sb, ' ')
}
}
write_operand(sb, &inst.ops[slot], offset_to_label, label_names, opts)
write_operand(sb, &inst.ops[slot], &display, opts)
}
}
strings.write_string(sb, opts.separator)
@@ -132,7 +131,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^isa.Label_Names = nil,
) {
sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -144,7 +143,7 @@ sbprintln :: proc(
print :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -153,7 +152,7 @@ print :: proc(
println :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -162,7 +161,7 @@ println :: proc(
aprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -172,7 +171,7 @@ aprint :: proc(
aprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -182,7 +181,7 @@ aprintln :: proc(
tprint :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -191,7 +190,7 @@ tprint :: proc(
tprintln :: proc(
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -201,7 +200,7 @@ tprintln :: proc(
bprint :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -211,7 +210,7 @@ bprint :: proc(
bprintln :: proc(
buf: []u8,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) -> string {
sb := strings.builder_from_bytes(buf)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -221,7 +220,7 @@ bprintln :: proc(
fprint :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -231,7 +230,7 @@ fprint :: proc(
fprintln :: proc(
fd: ^os.File,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -241,7 +240,7 @@ fprintln :: proc(
wprint :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -251,7 +250,7 @@ wprint :: proc(
wprintln :: proc(
w: io.Writer,
instructions: []Instruction, inst_info: []Instruction_Info, label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^map[u32]string = nil,
tokens: ^[dynamic]Token = nil, options: ^Print_Options = nil, label_names: ^isa.Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -344,11 +343,10 @@ write_register :: proc(sb: ^strings.Builder, r: Register, uppercase: bool, eleme
@(private="file")
write_operand :: proc(
sb: ^strings.Builder,
op: ^Operand,
offset_to_label: map[u32]u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
sb: ^strings.Builder,
op: ^Operand,
display: ^isa.Label_Display,
opts: ^Print_Options,
) {
switch op.kind {
case .NONE:
@@ -381,31 +379,14 @@ write_operand :: proc(
case .RELATIVE:
target := u32(op.relative)
if id, has := offset_to_label[target]; has {
write_label(sb, id, label_names, opts)
if isa.label_display_at(display, target) {
isa.label_display_write(display, sb, target, opts.label_prefix)
} else {
isa.print_hex(sb, u64(target), opts)
}
}
}
@(private="file")
write_label :: proc(
sb: ^strings.Builder,
label_id: u32,
label_names: ^map[u32]string,
opts: ^Print_Options,
) {
if label_names != nil {
if name, has := label_names^[label_id]; has {
strings.write_string(sb, name)
return
}
}
strings.write_string(sb, opts.label_prefix)
write_decimal_u32(sb, label_id)
}
@(private="file")
write_decimal_u32 :: proc(sb: ^strings.Builder, v: u32) {
if v == 0 {

View File

@@ -19,3 +19,5 @@ import "core:rexcode/isa"
Label_Definition :: isa.Label_Definition
Label_Map :: isa.Label_Map
LABEL_UNDEFINED :: isa.LABEL_UNDEFINED
Label_Offset :: isa.Label_Offset
Label_Names :: isa.Label_Names

View File

@@ -282,7 +282,7 @@ sbprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil, // Optional: for named label output (id → name)
label_names: ^Label_Names = nil, // Optional: for named label output (id → name)
) {
options := options != nil ? options^ : DEFAULT_PRINT_OPTIONS
@@ -300,30 +300,25 @@ sbprint :: proc(
}
}
// Display-side label naming: numbers in ADDRESS order (independent of the internal ids'
// allocation order), caller names keyed by byte offset (isa.Label_Display).
display: isa.Label_Display
isa.label_display_init(&display, label_defs, label_names)
defer isa.label_display_destroy(&display)
for &inst, instruction_index in instructions {
info := &inst_info[instruction_index]
// Check if there's a label at this offset
for label_def, label_id in label_defs {
if label_def != LABEL_UNDEFINED && u32(label_def) == info.offset {
// Print label definition
start := strings.builder_len(sb^)
name: string; ok: bool
if label_names != nil { name, ok = label_names^[u32(label_id)] }
if ok {
strings.write_string(sb, name)
} else {
strings.write_string(sb, options.label_prefix)
print_decimal(sb, u32(label_id))
}
strings.write_byte(sb, ':')
emit_token(tokens, sb, .LABEL_DEF, 0xFFFF, start)
// A displayable label at this offset — a definition, or a caller-named offset
if isa.label_display_at(&display, info.offset) {
start := strings.builder_len(sb^)
isa.label_display_write(&display, sb, info.offset, options.label_prefix)
strings.write_byte(sb, ':')
emit_token(tokens, sb, .LABEL_DEF, 0xFFFF, start)
start = strings.builder_len(sb^)
strings.write_string(sb, options.separator)
emit_token(tokens, sb, .NEWLINE, 0xFFFF, start)
break
}
start = strings.builder_len(sb^)
strings.write_string(sb, options.separator)
emit_token(tokens, sb, .NEWLINE, 0xFFFF, start)
}
// Print offset if requested, otherwise indent
@@ -384,31 +379,13 @@ sbprint :: proc(
write_memory_with_tokens(sb, op.mem, &options, tokens, u16(instruction_index))
case .RELATIVE:
// Compute absolute target and check if it matches a label
// Compute absolute target and name it if a displayable label sits there
inst_end := i64(info.offset) + i64(inst.length)
target := inst_end + op.relative
// Find label at this target
found_label: u32 = 0
found_label_valid := false
for lbl_id in 0..<u32(len(label_defs)) {
if label_defs[lbl_id] != LABEL_UNDEFINED && i64(label_defs[lbl_id]) == target {
found_label = lbl_id
found_label_valid = true
break
}
}
if found_label_valid {
if target >= 0 && target <= i64(max(u32)) && isa.label_display_at(&display, u32(target)) {
start := strings.builder_len(sb^)
name: string; ok: bool
if label_names != nil { name, ok = label_names^[found_label] }
if ok {
strings.write_string(sb, name)
} else {
strings.write_string(sb, options.label_prefix)
print_decimal(sb, found_label)
}
isa.label_display_write(&display, sb, u32(target), options.label_prefix)
emit_token(tokens, sb, .LABEL_REF, u16(instruction_index), start)
} else {
start := strings.builder_len(sb^)
@@ -558,7 +535,7 @@ sbprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
#force_inline sbprint(sb, instructions, inst_info, label_defs, tokens, options, label_names)
strings.write_byte(sb, '\n')
@@ -571,7 +548,7 @@ print :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
#force_inline sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -586,7 +563,7 @@ println :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
#force_inline sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -601,7 +578,7 @@ aprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -617,7 +594,7 @@ aprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
allocator := context.allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -633,7 +610,7 @@ tprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
allocator := context.temp_allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -649,7 +626,7 @@ tprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
allocator := context.temp_allocator,
) -> string {
sb := strings.builder_make(allocator)
@@ -666,7 +643,7 @@ bprint :: #force_inline proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) -> string {
sb := strings.builder_from_slice(buf)
#force_inline sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -682,7 +659,7 @@ bprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) -> string {
sb := strings.builder_from_slice(buf)
#force_inline sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -698,7 +675,7 @@ fprint :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
#force_inline sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -714,7 +691,7 @@ fprintln :: proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
#force_inline sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -730,7 +707,7 @@ wprint :: #force_inline proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprint(&sb, instructions, inst_info, label_defs, tokens, options, label_names)
@@ -746,7 +723,7 @@ wprintln :: #force_inline proc(
label_defs: []Label_Definition,
tokens: ^[dynamic]Token = nil,
options: ^Print_Options = nil,
label_names: ^map[u32]string = nil,
label_names: ^Label_Names = nil,
) {
sb := strings.builder_make(context.temp_allocator)
sbprintln(&sb, instructions, inst_info, label_defs, tokens, options, label_names)

View File

@@ -3010,10 +3010,11 @@ run_label_map_tests :: proc() {
x86.decode(code_buf[:byte_count], nil, &decoded_insts, &decoded_info, &decoded_labels, &decode_errors)
// Print with named labels (printer wants id→name; Label_Map stores name→id).
id_to_name := make(map[u32]string, len(lm.names), context.temp_allocator)
for name, id in lm.names { id_to_name[id] = name }
output := x86.tprint(decoded_insts[:], decoded_info[:], lm.labels[:], label_names=&id_to_name)
// Print with named labels (printer wants BYTE OFFSET → name; Label_Map stores name → id, and
// after encode each id's Label_Definition holds its byte offset).
names := make(x86.Label_Names, len(lm.names), context.temp_allocator)
for name, id in lm.names { names[x86.Label_Offset(u32(lm.labels[id]))] = name }
output := x86.tprint(decoded_insts[:], decoded_info[:], lm.labels[:], label_names=&names)
// Verify output contains named labels
// Note: JNZ and JNE are the same instruction, decoder may output either