mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-04 13:18:31 +00:00
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:
@@ -142,9 +142,9 @@ x86.label_set(&lm, "done", &instructions)
|
||||
result := x86.encode(instructions[:], lm.labels[:], code[:], &relocs, &errors)
|
||||
|
||||
// Printer wants id→name; Label_Map stores name→id, 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`)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user