diff --git a/gen/instruction.go b/gen/instruction.go new file mode 100644 index 0000000..24aecca --- /dev/null +++ b/gen/instruction.go @@ -0,0 +1,15 @@ +package gen + +import "github.com/firestuff/subcoding/vm" + +func randInstruction() *vm.Instruction { + instr := &vm.Instruction{ + OpCode: randOpCode(), + } + + for i, t := range vm.OperandsByOpCode[instr.OpCode] { + instr.Operands[i] = randOperand(t) + } + + return instr +} diff --git a/gen/opcode.go b/gen/opcode.go new file mode 100644 index 0000000..5f69977 --- /dev/null +++ b/gen/opcode.go @@ -0,0 +1,52 @@ +package gen + +import "math/rand" + +import "github.com/firestuff/subcoding/vm" + +var opCodes = []vm.OpCodeType{ + vm.OpNop, + + vm.OpMov, + + vm.OpAdd, + vm.OpSub, + vm.OpMul, + vm.OpDivU, + vm.OpDivS, + + vm.OpNot, + vm.OpAnd, + vm.OpOr, + vm.OpXor, + + vm.OpShR, + vm.OpShL, + + vm.OpEq, + vm.OpLTU, + vm.OpLTS, + vm.OpGTU, + vm.OpGTS, + vm.OpLTEU, + vm.OpLTES, + vm.OpGTEU, + vm.OpGTES, + + vm.OpJmp, + vm.OpJmpT, + vm.OpJmpF, + + vm.OpCal, + vm.OpCalT, + vm.OpCalF, + + vm.OpRet, + vm.OpRetT, + vm.OpRetF, +} + +func randOpCode() vm.OpCodeType { + // Uniform distribution + return opCodes[rand.Intn(len(opCodes))] +} diff --git a/gen/operand.go b/gen/operand.go new file mode 100644 index 0000000..0fc659b --- /dev/null +++ b/gen/operand.go @@ -0,0 +1,50 @@ +package gen + +import "math/rand" + +import "github.com/firestuff/subcoding/vm" + +func randOperand(t vm.OperandNumericType) *vm.Operand { + for { + op := &vm.Operand{ + Type: randOperandType(), + } + + switch op.Type { + case vm.GlobalMemoryIndex: + op.Value = RandBiasedUint64() + + case vm.FunctionMemoryIndex: + op.Value = RandBiasedUint64() + + case vm.Literal: + switch t { + case vm.OperandUnsigned: + op.Value = RandBiasedUint64() + + case vm.OperandSigned: + op.Value = RandBiasedInt64() + + case vm.OperandSignedOrUnsigned: + op.Value = RandBiasedUSint64() + + case vm.OperandReference: + // Invalid. Roll the dice again. + continue + } + } + + return op + } +} + +var operandTypes = []vm.OperandType{ + vm.Literal, + vm.FunctionMemoryIndex, + vm.GlobalMemoryIndex, +} + +func randOperandType() vm.OperandType { + // Uniform distribution + return operandTypes[rand.Intn(len(operandTypes))] +} diff --git a/gen/program.go b/gen/program.go new file mode 100644 index 0000000..901c012 --- /dev/null +++ b/gen/program.go @@ -0,0 +1,15 @@ +package gen + +import "github.com/firestuff/subcoding/vm" + +func RandProgram() *vm.Program { + return &vm.Program{ + Functions: []*vm.Function{ + &vm.Function{ + Instructions: []*vm.Instruction{ + randInstruction(), + }, + }, + }, + } +} diff --git a/gen/rand.go b/gen/rand.go index ca1bcbd..021ee65 100644 --- a/gen/rand.go +++ b/gen/rand.go @@ -11,14 +11,24 @@ func RandBiasedUint64() uint64 { // Generate a random int64 with an even distribution of the tuple // {sign, bits.Len64(math.Abs())} -func RandBiasedInt64() int64 { +func RandBiasedInt64() uint64 { shift := rand.Intn(127) // [0,62]: positive // [63,63]: zero // [64,126]: negative if shift < 64 { - return int64((rand.Uint64() | 0x8000000000000000) >> (shift + 1)) + return uint64(int64((rand.Uint64() | 0x8000000000000000) >> (shift + 1))) } else { - return int64((rand.Uint64() | 0x8000000000000000) >> (shift - 63)) * -1 + return uint64(int64((rand.Uint64() | 0x8000000000000000) >> (shift - 63)) * -1) + } +} + +// Mixture of RandBiasedUint64() and RandBiasedInt64(), with probability shifted +// toward more unsigned values. +func RandBiasedUSint64() uint64 { + if rand.Intn(2) == 0 { + return RandBiasedUint64() + } else { + return RandBiasedInt64() } } diff --git a/test/gen_test.go b/test/gen_test.go new file mode 100644 index 0000000..6a100ff --- /dev/null +++ b/test/gen_test.go @@ -0,0 +1,9 @@ +package test + +import "testing" + +import "github.com/firestuff/subcoding/gen" + +func TestRandProgram(t *testing.T) { + gen.RandProgram() +} diff --git a/test/rand_test.go b/test/rand_test.go index 39e6127..d13c54e 100644 --- a/test/rand_test.go +++ b/test/rand_test.go @@ -43,7 +43,7 @@ func TestRandBiasedInt64(t *testing.T) { buckets := [127]uint64{} for i := 0; i < 1000000; i++ { - val := gen.RandBiasedInt64() + val := int64(gen.RandBiasedInt64()) switch { case val == 0: buckets[63]++