Files
subcoding/asm/disassemble.go

101 lines
2.2 KiB
Go
Raw Normal View History

2021-11-19 20:38:56 -10:00
package asm
import "fmt"
2021-11-20 10:10:21 -10:00
import "math"
2021-11-20 09:46:51 -10:00
import "strings"
2021-11-19 20:38:56 -10:00
import "github.com/firestuff/subcoding/vm"
import "github.com/pkg/errors"
2021-11-20 10:10:21 -10:00
// Lots of manual yaml assembly because the yaml package is missing features (flow in nested arrays)
func Disassemble(prog *vm.Program) (string, error) {
fncs := []string{}
2021-11-19 20:38:56 -10:00
for f, fnc := range prog.Functions {
2021-11-20 10:10:21 -10:00
dis, err := disassembleFunction(fnc)
2021-11-19 20:38:56 -10:00
if err != nil {
2021-11-20 10:10:21 -10:00
return "", errors.Wrapf(err, "At function index %d", f)
2021-11-19 20:38:56 -10:00
}
2021-11-20 10:10:21 -10:00
fncs = append(fncs, dis)
2021-11-19 20:38:56 -10:00
}
2021-11-20 18:27:06 -10:00
return fmt.Sprintf(`global_memory_size: %d
function_memory_size: %d
2021-11-20 19:25:16 -10:00
instruction_limit: %d
2021-11-20 18:27:06 -10:00
functions:
%s`,
prog.GlobalMemorySize,
prog.FunctionMemorySize,
2021-11-20 19:25:16 -10:00
prog.InstructionLimit,
2021-11-20 18:27:06 -10:00
strings.Join(fncs, ""),
), nil
2021-11-19 20:38:56 -10:00
}
2021-11-20 10:10:21 -10:00
func disassembleFunction(fnc *vm.Function) (string, error) {
instrs := []string{}
2021-11-19 20:38:56 -10:00
for i, instr := range fnc.Instructions {
2021-11-20 10:10:21 -10:00
dis, err := disassembleInstruction(instr)
2021-11-19 20:38:56 -10:00
if err != nil {
2021-11-20 10:10:21 -10:00
return "", errors.Wrapf(err, "At instruction index %d", i)
2021-11-19 20:38:56 -10:00
}
2021-11-20 10:10:21 -10:00
instrs = append(instrs, dis)
2021-11-19 20:38:56 -10:00
}
2021-11-20 10:10:21 -10:00
return fmt.Sprintf("- - %s\n", strings.Join(instrs, "\n - ")), nil
2021-11-19 20:38:56 -10:00
}
2021-11-20 10:10:21 -10:00
func disassembleInstruction(in *vm.Instruction) (string, error) {
2021-11-20 09:46:51 -10:00
parts := []string{
nameByOpCode[in.OpCode],
}
2021-11-19 20:38:56 -10:00
2021-11-20 17:26:58 -10:00
for i, t := range vm.OperandsByOpCode[in.OpCode] {
2021-11-20 10:10:21 -10:00
op, err := disassembleOperand(in.Operands[i], t)
if err != nil {
return "", err
}
parts = append(parts, op)
}
2021-11-20 09:46:51 -10:00
encoded := fmt.Sprintf("[%s]", strings.Join(parts, ", "))
2021-11-20 10:10:21 -10:00
return encoded, nil
}
2021-11-20 17:26:58 -10:00
func disassembleOperand(op *vm.Operand, t vm.OperandNumericType) (string, error) {
2021-11-20 10:10:21 -10:00
switch op.Type {
case vm.GlobalMemoryIndex:
return fmt.Sprintf("g%d", op.Value), nil
case vm.FunctionMemoryIndex:
return fmt.Sprintf("f%d", op.Value), nil
case vm.Literal:
switch t {
2021-11-20 17:26:58 -10:00
case vm.OperandUnsigned:
2021-11-20 10:10:21 -10:00
return fmt.Sprintf("%d", op.Value), nil
2021-11-20 17:26:58 -10:00
case vm.OperandSigned:
2021-11-20 10:10:21 -10:00
return fmt.Sprintf("%+d", int64(op.Value)), nil
2021-11-20 17:26:58 -10:00
case vm.OperandSignedOrUnsigned:
2021-11-20 10:10:21 -10:00
// Take our best guess
if op.Value > math.MaxInt64 {
return fmt.Sprintf("%+d", int64(op.Value)), nil
} else {
return fmt.Sprintf("%d", op.Value), nil
}
default:
return "", fmt.Errorf("Invalid operand assembler type: %d", t)
}
default:
return "", fmt.Errorf("Invalid operand type: %d", op.Type)
}
2021-11-19 20:38:56 -10:00
}