コード例 #1
0
ファイル: assembler_test.go プロジェクト: tizgrape/gojit
func newAsm(t testing.TB) *Assembler {
	buf, e := gojit.Alloc(gojit.PageSize)
	if e != nil {
		t.Fatalf("alloc: ", e.Error())
	}
	return &Assembler{buf, 0, CgoABI}
}
コード例 #2
0
ファイル: geninst_test.go プロジェクト: tizgrape/gojit
func testSimple(name string, t *testing.T, cases []simple) {
	buf, e := gojit.Alloc(gojit.PageSize)
	if e != nil {
		t.Fatalf(e.Error())
	}
	defer gojit.Release(buf)

	for i, tc := range cases {
		asm := &Assembler{Buf: buf}
		begin(asm)
		tc.f(asm)
		f := finish(asm)

		runtime.GC()

		for j := 0; j < len(tc.inout); j += 2 {
			in := tc.inout[j]
			out := tc.inout[j+1]
			got := f(in)
			if out != got {
				t.Errorf("f(%s)[%d](%x) = %x, expect %x",
					name, i, in, got, out)
			}
		}
	}
}
コード例 #3
0
ファイル: assembler.go プロジェクト: tizgrape/gojit
func NewGoABI(size int) (*Assembler, error) {
	buf, e := gojit.Alloc(size)
	if e != nil {
		return nil, e
	}
	return &Assembler{Buf: buf, ABI: GoABI}, nil
}
コード例 #4
0
ファイル: bf.go プロジェクト: tizgrape/gojit
// Compile compiles a brainfuck program (represented as a byte slice)
// into a Go function. The function accepts as an argument the tape to
// operate on. The provided Reader and Writer are used to implement
// `,' and `.', respectively.
//
// The compiled code does no bounds-checking on the tape. On EOF or
// other read error, `,' clears the current cell.
func Compile(prog []byte, r io.Reader, w io.Writer) (func([]byte), error) {
	buf, e := gojit.Alloc(gojit.PageSize * 4)
	if e != nil {
		return nil, e
	}

	cc := &compiled{buf: buf, r: r.Read, w: w.Write}

	asm := &amd64.Assembler{Buf: buf, ABI: abi}
	asm.Mov(amd64.Indirect{amd64.Rdi, 0, 64}, amd64.Rax)

	opcodes, e := optimize(prog)
	if e != nil {
		return nil, e
	}

	for _, op := range opcodes {
		switch op.op {
		case '+':
			asm.Addb(amd64.Imm{int32(op.repeat)},
				amd64.Indirect{amd64.Rax, 0, 8})
		case '-':
			asm.Subb(amd64.Imm{int32(op.repeat)},
				amd64.Indirect{amd64.Rax, 0, 8})
		case '<':
			asm.Sub(amd64.Imm{int32(op.repeat)}, amd64.Rax)
		case '>':
			asm.Add(amd64.Imm{int32(op.repeat)}, amd64.Rax)
		case '.':
			emitDot(asm, cc)
		case ',':
			emitComma(asm, cc)
		case '[':
			emitLbrac(asm, cc)
		case ']':
			emitRbrac(asm, cc)
		}
	}

	asm.Ret()

	asm.BuildTo(&cc.code)
	return cc.run, nil
}
コード例 #5
0
ファイル: geninst_test.go プロジェクト: tizgrape/gojit
func TestArith(t *testing.T) {
	cases := []struct {
		insn     *Instruction
		lhs, rhs int32
		out      uintptr
	}{
		{InstAdd, 20, 30, 50},
		{InstAdd, 0x7fffffff, 0x70000001, 0xf0000000},
		{InstAnd, 0x77777777, U32(0xffffffff), 0x77777777},
		{InstAnd, 0x77777777, U32(0x88888888), 0},
		{InstOr, 0x77777777, U32(0x88888888), 0xffffffff},
		{InstOr, 1, 0, 1},
		{InstSub, 5, 10, 5},
		{InstSub, 10, 5, 0xfffffffffffffffb},
	}

	buf, e := gojit.Alloc(gojit.PageSize)
	if e != nil {
		t.Fatalf(e.Error())
	}
	defer gojit.Release(buf)

	for _, tc := range cases {
		asm := &Assembler{buf, 0, CgoABI}
		var funcs []func(uintptr) uintptr
		if tc.insn.imm_r.ok() {
			begin(asm)
			asm.Mov(Imm{tc.rhs}, Rax)
			asm.Arithmetic(tc.insn, Imm{tc.lhs}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.imm_rm.op.ok() {
			begin(asm)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.rhs}, Indirect{Rdi, 0, 32})
			asm.Arithmetic(tc.insn, Imm{tc.lhs}, Indirect{Rdi, 0, 64})
			asm.Mov(Indirect{Rdi, 0, 64}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.r_rm.ok() {
			begin(asm)
			asm.Mov(Imm{tc.lhs}, R10)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.rhs}, Indirect{Rdi, 0, 32})
			asm.Arithmetic(tc.insn, R10, Indirect{Rdi, 0, 64})
			asm.Mov(Indirect{Rdi, 0, 64}, Rax)
			funcs = append(funcs, finish(asm))
		}
		if tc.insn.rm_r.ok() {
			begin(asm)
			asm.Mov(Imm{0}, Indirect{Rdi, 0, 0})
			asm.Mov(Imm{tc.lhs}, Indirect{Rdi, 0, 32})
			asm.Mov(Imm{tc.rhs}, R10)
			asm.Arithmetic(tc.insn, Indirect{Rdi, 0, 64}, R10)
			asm.Mov(R10, Rax)
			funcs = append(funcs, finish(asm))
		}

		for i, f := range funcs {
			got := f(gojit.Addr(mem))
			if got != tc.out {
				t.Errorf("%s(0x%x,0x%x) [%d] = 0x%x (expect 0x%x)",
					tc.insn.Mnemonic, tc.lhs, tc.rhs, i, got, tc.out)
			} else if testing.Verbose() {
				// We don't use `testing.Logf` because
				// if we panic inside JIT'd code, the
				// runtime dies horrible (rightfully
				// so!), and so the `testing` cleanup
				// code never runs, and we never see
				// log messages. We want to get these
				// out as soon as possible, so we
				// write them directly.
				fmt.Printf("OK %d %s(0x%x,0x%x) = 0x%x\n",
					i, tc.insn.Mnemonic, tc.lhs, tc.rhs, got)
			}
		}
	}
}