diff --git a/internal/pkg/asm.go b/internal/pkg/asm.go index 86fc1e4a..73c63040 100644 --- a/internal/pkg/asm.go +++ b/internal/pkg/asm.go @@ -6,9 +6,71 @@ import ( "io" "strconv" "strings" + "unique" ) -type asmOutLine struct { +type AsmMessage struct { + data AsmData + sig AsmSig +} +type AsmGenerator struct { + i uintptr + as chan AsmMessage + lbl []uintptr +} +type AsmSig int + +const ( + AsmSigEnd AsmSig = iota + AsmSigLbl + AsmSigHead + AsmSigVal +) + +// GenerateAll collects all asm sent to this generator and outputs formatted data to the given [io.Writer]. +func (g *AsmGenerator) GenerateAll(w io.Writer) error { + for a := <-g.as; a.sig != AsmSigEnd; a = <-g.as { + switch a.sig { + case AsmSigLbl: + + break + case AsmSigHead: + + break + case AsmSigVal: + _, err := w.Write([]byte(a.data.Line(g))) + if err != nil { + return err + } + break + default: + panic("invalid asm signal") + } + } + return nil +} + +type AsmFormatter struct { + // if false, generate labels. if true, bare idents will be shown. + Real bool + // if true, header data and the dependencies list will be shown. + ShowHeader bool + // if true, don't generate raw byte data (only generate raw assembly). + Raw bool +} +type AsmData interface { + Line(*AsmGenerator) string + Offset(int) +} + +type AsmDataNone struct{} + +func (a AsmDataNone) Line(*AsmGenerator) string { + return "" +} +func (a AsmDataNone) Offset(int) {} + +type AsmLine struct { pos int word int kindData int64 @@ -18,7 +80,22 @@ type asmOutLine struct { value string } -var spacingLine = asmOutLine{ +func (l AsmLine) Line(gen *AsmGenerator) string { + return "" +} +func (l AsmLine) Offset(offset int) { + l.pos += offset +} + +type AsmHeaderLine struct { + pos int + kind string + kindData int64 + label string + id unique.Handle[ID] +} + +var spacingLine = AsmLine{ pos: -1, kindData: -1, valueData: nil, @@ -28,7 +105,7 @@ var spacingLine = asmOutLine{ } func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) (s string, err error) { - var lines []asmOutLine + var lines []AsmLine sb := new(strings.Builder) header := true pos := new(int) @@ -46,10 +123,10 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) break } if showHeader { - lines = append(lines, asmOutLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""}) + lines = append(lines, AsmLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""}) } for i := 0; uint64(i) < size; i++ { - var did Checksum + var did ID var dkind uint64 p := *pos if _, dkind, err = nextUint64(r, pos); err != nil { @@ -59,7 +136,7 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) break } if showHeader { - lines = append(lines, asmOutLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)}) + lines = append(lines, AsmLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)}) } } header = false @@ -82,9 +159,9 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) if _, sum, err = nextIdent(r, pos); err != nil { break } - lines = append(lines, asmOutLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)}) + lines = append(lines, AsmLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)}) } else { - lines = append(lines, asmOutLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""}) + lines = append(lines, AsmLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""}) } lines = append(lines, spacingLine) header = true @@ -96,12 +173,12 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) if a, _, err = nextUint32(r, pos); err != nil { break } - var sum Checksum - if _, sum, err = nextIdent(r, pos); err != nil { + var id ID + if _, id, err = nextIdent(r, pos); err != nil { break } - lines = append(lines, asmOutLine{p, 4, int64(kind), a, 1, "id ", Encode(sum)}) + lines = append(lines, AsmLine{p, 4, int64(kind), a, 1, "id ", Encode(id)}) continue case IRKindUint32: var i uint32 @@ -109,7 +186,7 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) if bi, i, err = nextUint32(r, pos); err != nil { break } - lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)}) + lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)}) case IRKindString: var l uint32 var bl []byte @@ -123,14 +200,14 @@ func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) } *pos = *pos + n - lines = append(lines, asmOutLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))}) + lines = append(lines, AsmLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))}) continue default: var bi []byte if bi, _, err = nextUint32(r, pos); err != nil { break } - lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "????", ""}) + lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "????", ""}) } } if err != io.EOF { @@ -182,14 +259,14 @@ func nextUint64(r io.Reader, pos *int) ([]byte, uint64, error) { *pos = p return i, binary.LittleEndian.Uint64(i), nil } -func nextIdent(r io.Reader, pos *int) ([]byte, Checksum, error) { +func nextIdent(r io.Reader, pos *int) ([]byte, ID, error) { i := make([]byte, 48) if _, err := r.Read(i); err != nil { - return i, Checksum{}, err + return i, ID{}, err } p := *pos + 48 *pos = p - return i, Checksum(i), nil + return i, ID(i), nil } func intToKind(i uint64) string { switch Kind(i) {