コード例 #1
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) BeginStack(start, end bitgen.Line) {
	if w.Offset != 0 {
		panic("BeginStack while in stack")
	}

	next := w.ReserveLine()
	w.Assign(start, w.Prev, w.Stack.Ptr, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, bitgen.Integer{bitgen.ValueAt{w.Alloc.Ptr}, 32}, w.Stack.Num, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, w.Stack.Num, w.Alloc.Num, next)
	start = next

	next = w.ReserveLine()
	w.Assign(start, w.Stack.Ptr, w.Alloc.Ptr, next)
	start = next

	w.Offset = uint(3)
	next = w.ReserveLine()
	w.Add(start, w.Alloc.Num, uint64(w.Offset*32/8), next, 0)
	start = next

	next = w.ReserveLine()
	w.Assign(start, w.Alloc.Ptr, bitgen.Offset{w.Alloc.Ptr, w.Offset * 32}, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, w.StackOffset(32/8), w.This.Num, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, w.StackOffset(32/8+32/8), w.Goto, next)
	start = next

	for i := 0; i < 32; i++ {
		next = w.ReserveLine()
		w.Assign(start, w.This.Num.Bit(uint(i)), bitgen.Bit(false), next)
		start = next

		next = w.ReserveLine()
		w.Assign(start, w.Goto.Bit(uint(i)), bitgen.Bit(false), next)
		start = next
	}

	w.Assign(start, w.This.Ptr, w.Heap, end)
}
コード例 #2
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) gotoNext(start bitgen.Line, nextVal uint32, end bitgen.Line) {
	for i := uint(0); i < 32; i++ {
		var next bitgen.Line
		if i == 32-1 {
			next = w.JumpTableEntry
		} else {
			next = w.ReserveLine()
		}
		w.Assign(start, w.Next.Bit(i), bitgen.Bit((nextVal>>i)&1 == 1), next)
		start = next
	}

	if w.Jumps[nextVal] != 0 || end != 0 {
		w.Jump(w.Jumps[nextVal], bitgen.Bit(false), end, end)
	}
}
コード例 #3
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) SaveRegisters(start, end bitgen.Line) {
	if w.Offset == 0 {
		panic("SaveRegisters while not in stack")
	}

	for i := range w.General {
		next := w.ReserveLine()
		w.Save[i], _ = w.StackAlloc(start, next)
		start = next

		next = w.ReserveLine()
		w.Copy(start, w.Save[i], w.General[i].Num, next)
		start = next

		for j := uint(0); j < 32; j++ {
			next = w.ReserveLine()
			w.Assign(start, w.General[i].Num.Bit(j), bitgen.Bit(false), next)
			start = next
		}

		if i == len(w.General)-1 {
			next = end
		} else {
			next = w.ReserveLine()
		}
		w.Assign(start, w.General[i].Ptr, w.Heap, next)
		start = next
	}
}
コード例 #4
0
ファイル: ast.go プロジェクト: BenLubar/bit
func (e *NullExpr) write(w *writer, start, end bitgen.Line) {
	for i := uint(0); i < w.Return.Num.Width; i++ {
		next := w.ReserveLine()
		w.Assign(start, w.Return.Num.Bit(i), bitgen.Bit(false), next)
		start = next
	}
	w.Assign(start, w.Return.Ptr, w.Heap, end)
}
コード例 #5
0
ファイル: opt_test.go プロジェクト: BenLubar/bit
func TestOptAlloc64(t *testing.T) {
	testOptRaw(t, func(w *bitgen.Writer) (n int64, err error) {
		type register struct {
			Ptr bitgen.Variable
			Num bitgen.Integer
		}
		reg := register{
			Ptr: w.ReserveVariable(),
			Num: w.ReserveInteger(32),
		}
		alloc := register{
			Ptr: w.ReserveVariable(),
			Num: w.ReserveInteger(32),
		}
		heapStart := bitgen.AddressOf{w.ReserveHeap()}

		var start bitgen.Line
		for _, r := range []register{reg, alloc} {
			for i := uint(0); i < r.Num.Width; i++ {
				next := w.ReserveLine()
				w.Assign(start, r.Num.Bit(i), bitgen.Bit(false), next)
				start = next
			}

			next := w.ReserveLine()
			w.Assign(start, r.Ptr, heapStart, next)
			start = next
		}

		next := w.ReserveLine()
		w.Increment(start, alloc.Num, next, 0)
		start = next

		next = w.ReserveLine()
		w.Assign(start, alloc.Ptr, bitgen.Offset{alloc.Ptr, 8}, next)
		start = next

		next = w.ReserveLine()
		w.Copy(start, reg.Num, alloc.Num, next)
		start = next

		next = w.ReserveLine()
		w.Assign(start, reg.Ptr, alloc.Ptr, next)
		start = next

		const size = 64 / 8

		next = w.ReserveLine()
		w.Add(start, alloc.Num, size, next, 0)
		start = next

		w.Assign(start, alloc.Ptr, bitgen.Offset{alloc.Ptr, 8 * size}, 0)

		return
	})
}
コード例 #6
0
ファイル: ast.go プロジェクト: BenLubar/bit
func (e *MatchExpr) write(w *writer, start, end bitgen.Line) {
	next := w.ReserveLine()
	e.Left.write(w, start, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, e.slot, w.Return.Num, next)
	start = next

	null := w.CaseNull
findNull:
	for _, c := range e.Cases {
		for _, h := range c.classes {
			if h == basicDummyNull {
				null = w.ReserveLine()
				break findNull
			}
		}
	}

	next = w.ReserveLine()
	w.Cmp(start, w.Return.Num, 0, null, next)
	start = next

	for _, c := range e.Cases {
		hasNull := false
		for _, h := range c.classes {
			if h == basicDummyNull {
				hasNull = true
				break
			}
		}
		target := null
		if !hasNull {
			target = w.ReserveLine()
		}

		for _, h := range c.classes {
			if !w.AST.usedTypes[h] {
				continue
			}

			next = w.ReserveLine()
			w.CmpReg(start, bitgen.Integer{bitgen.ValueAt{w.Return.Ptr}, 32}, w.Classes[h].Num, target, next)
			start = next
		}

		c.Body.write(w, target, end)
	}

	w.Jump(start, bitgen.Bit(false), w.NoCase, w.NoCase)
}
コード例 #7
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) MethodTables(start, end bitgen.Line) {
	methods := func(start bitgen.Line, c *ClassDecl, end bitgen.Line) {
		cr := w.Classes[c].Ptr
		for i := uint(0); i < uint(len(c.methods)); i++ {
			for _, m := range c.methods {
				if m.offset != i {
					continue
				}
				jump := w.MethodStarts[m]
				for j := uint(32 - 1); j < 32; j-- {
					if (jump>>j)&1 == 0 {
						continue
					}
					var next bitgen.Line
					if i == uint(len(c.methods))-1 && jump&(1<<j-1) == 0 {
						next = end
					} else {
						next = w.ReserveLine()
					}

					w.Assign(start, bitgen.ValueAt{bitgen.Offset{cr, 32 + 32*i + j}}, bitgen.Bit(true), next)

					start = next
				}
			}
		}
	}

	var next bitgen.Line
	for _, c := range basicClasses {
		next = w.ReserveLine()
		methods(start, c, next)
		start = next
	}

	var usedClasses []*ClassDecl
	for _, c := range w.AST.Classes {
		if w.AST.usedTypes == nil || w.AST.usedTypes[c] {
			usedClasses = append(usedClasses, c)
		}
	}

	for i, c := range usedClasses {
		if i == len(usedClasses)-1 {
			next = end
		} else {
			next = w.ReserveLine()
		}
		methods(start, c, next)
		start = next
	}
}
コード例 #8
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) StaticCall(start bitgen.Line, m *StaticCallExpr, end bitgen.Line) {
	w.EndStack()

	nextVal := w.StaticCalls[m]
	gotoVal := w.MethodStarts[m.Name.target.(*MethodFeature)]

	for i := uint(0); i < 32; i++ {
		next := w.ReserveLine()
		w.Assign(start, w.Goto.Bit(i), bitgen.Bit((gotoVal>>i)&1 == 1), next)
		start = next
	}

	w.gotoNext(start, nextVal, end)
}
コード例 #9
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) NewInt(start bitgen.Line, reg register, value int32, end bitgen.Line) {
	next := w.ReserveLine()
	w.NewNative(start, reg, w.basicInt, 32/8, next)
	start = next

	for i := uint(0); i < 32; i++ {
		if i == 32-1 {
			next = end
		} else {
			next = w.ReserveLine()
		}
		w.Assign(start, bitgen.ValueAt{bitgen.Offset{reg.Ptr, 32 + i}}, bitgen.Bit((uint32(value)>>uint(i))&1 == 1), next)
		start = next
	}
}
コード例 #10
0
ファイル: opt_test.go プロジェクト: BenLubar/bit
func TestOptZero32(t *testing.T) {
	testOptRaw(t, func(w *bitgen.Writer) (n int64, err error) {
		num := w.ReserveInteger(32)

		var start bitgen.Line
		for i := uint(0); i < num.Width; i++ {
			var next bitgen.Line
			if i != num.Width-1 {
				next = w.ReserveLine()
			}
			var nn int64
			nn, err = w.Assign(start, num.Bit(i), bitgen.Bit(false), next)
			n += nn
			if err != nil {
				return
			}
			start = next
		}
		return
	})
}
コード例 #11
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) NewArrayAny(start bitgen.Line, end bitgen.Line) {
	w.EndStack()

	next := w.ReserveLine()
	w.Load(start, w.General[0], w.Stack, w.Arg(0), next)
	start = next

	// 1<<2 == 32/8

	for i := uint(0); i <= 2; i++ {
		next = w.ReserveLine()
		w.Jump(start, bitgen.ValueAt{bitgen.Offset{w.General[0].Ptr, 32 + 32 - 1 - i}}, next, w.IndexRange)
		start = next
	}

	// multiply array size by 32/8 (elements -> bytes)
	next = w.ReserveLine()
	w.Copy(start, w.Return.Num.Sub(2, 32), w.IntValue(w.General[0].Ptr).Sub(0, 32-2), next)
	start = next

	// clear the bottom 2 bits
	for i := uint(0); i < 2; i++ {
		next = w.ReserveLine()
		w.Assign(start, w.Return.Num.Bit(i), bitgen.Bit(false), next)
		start = next
	}

	next = w.ReserveLine()
	w.NewNativeDynamic(start, w.Return, w.basicArrayAny, w.Return.Num, next)
	start = next

	next = w.ReserveLine()
	w.Copy(start, bitgen.Integer{bitgen.ValueAt{bitgen.Offset{w.Return.Ptr, basicArrayAnyLength.offset * 8}}, 32}, w.General[0].Num, next)
	start = next

	w.PopStack(start, end)
}
コード例 #12
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) NewString(start bitgen.Line, reg, length register, value string, end bitgen.Line) {
	next := w.ReserveLine()
	w.NewInt(start, length, int32(len(value)), next)
	start = next

	next = w.ReserveLine()
	w.NewNative(start, reg, basicString, uint(len(value)), next)
	start = next

	for i := range value {
		for j := 0; j < 8; j++ {
			next = w.ReserveLine()
			w.Assign(start, bitgen.ValueAt{bitgen.Offset{reg.Ptr, basicStringLength.offset*8 + 32 + uint(i*8+j)}}, bitgen.Bit((value[i]>>uint(j))&1 == 1), next)
			start = next
		}
	}

	w.Copy(start, bitgen.Integer{bitgen.ValueAt{bitgen.Offset{reg.Ptr, basicStringLength.offset * 8}}, 32}, length.Num, end)
}
コード例 #13
0
ファイル: codegen.go プロジェクト: BenLubar/bit
func (w *writer) Init() (start bitgen.Line) {
	w.basicInt = basicInt
	w.basicString = basicString
	w.basicArrayAny = basicArrayAny
	w.basicClasses = basicClasses

	var registers []register
	reg := func(r *register) {
		r.Ptr = w.ReserveVariable()
		r.Num = w.ReserveInteger(32)
		registers = append(registers, *r)
	}

	w.Goto = w.ReserveInteger(32)
	w.Next = w.ReserveInteger(32)
	w.Ptr = w.ReserveInteger(32)
	reg(&w.Alloc)
	reg(&w.Unit)
	reg(&w.True)
	reg(&w.False)
	reg(&w.Zero)
	reg(&w.Symbol)
	reg(&w.Return)
	reg(&w.This)
	reg(&w.Stack)
	w.Prev = w.ReserveVariable()
	for i := range w.General {
		reg(&w.General[i])
	}
	w.Classes = make(map[*ClassDecl]register)
	for _, c := range basicClasses {
		var r register
		reg(&r)
		w.Classes[c] = r
	}
	for _, c := range w.AST.Classes {
		if w.AST.usedTypes == nil || w.AST.usedTypes[c] {
			var r register
			reg(&r)
			w.Classes[c] = r
		}
	}
	w.Heap = bitgen.AddressOf{w.ReserveHeap()}

	for _, r := range registers {
		for i := uint(0); i < 32; i++ {
			next := w.ReserveLine()
			w.Assign(start, r.Num.Bit(i), bitgen.Bit(false), next)
			start = next
		}

		next := w.ReserveLine()
		w.Assign(start, r.Ptr, w.Heap, next)
		start = next
	}

	next := w.ReserveLine()
	w.Increment(start, w.Alloc.Num, next, 0)
	start = next

	next = w.ReserveLine()
	w.Assign(start, w.Alloc.Ptr, bitgen.Offset{w.Alloc.Ptr, 8}, next)
	start = next

	w.Panic = w.ReserveLine()
	w.Dump(w.Panic, 0)

	w.Null = w.Abort("runtime error: null pointer dereference\n")

	w.IndexRange = w.Abort("runtime error: index out of range\n")

	w.CaseNull = w.ReserveLine()
	w.PrintString(w.CaseNull, "runtime error: missing case for Null\n", 0)

	w.NoCase = w.ReserveLine()
	noCaseB := w.ReserveLine()
	w.PrintString(w.NoCase, "runtime error: missing case for ", noCaseB)
	noCaseA := noCaseB

	noCaseB = w.ReserveLine()
	w.Copy(noCaseA, w.StackOffset(w.Arg(0)), bitgen.Integer{bitgen.ValueAt{w.Return.Ptr}, 32}, noCaseB)
	noCaseA = noCaseB

	noCaseB = w.ReserveLine()
	w.PrintStringArg(noCaseA, 0, noCaseB)
	noCaseA = noCaseB

	w.Print(noCaseA, '\n', 0)

	w.DivZero = w.Abort("runtime error: division by zero\n")

	w.HeapRange = w.Abort("runtime error: pointer outside of heap\n")

	for _, c := range basicClasses {
		next = w.ReserveLine()
		w.ClassDecl(start, c, next)
		start = next
	}
	for _, c := range w.AST.Classes {
		if w.AST.usedTypes == nil || w.AST.usedTypes[c] {
			next = w.ReserveLine()
			w.ClassDecl(start, c, next)
			start = next
		}
	}

	for _, c := range basicClasses {
		next = w.ReserveLine()
		w.ClassDeclFixup(start, c, next)
		start = next
	}
	for _, c := range w.AST.Classes {
		if w.AST.usedTypes == nil || w.AST.usedTypes[c] {
			next = w.ReserveLine()
			w.ClassDeclFixup(start, c, next)
			start = next
		}
	}

	next = w.ReserveLine()
	w.NewNative(start, w.Unit, basicUnit, 0, next)
	start = next

	next = w.ReserveLine()
	w.NewNative(start, w.True, basicBoolean, 0, next)
	start = next

	next = w.ReserveLine()
	w.NewNative(start, w.False, basicBoolean, 0, next)
	start = next

	next = w.ReserveLine()
	w.NewInt(start, w.Zero, 0, next)
	start = next

	next = w.ReserveLine()
	w.CopyReg(start, w.General[0], w.General[2], next)
	start = next

	next = w.ReserveLine()
	w.CopyReg(start, w.General[1], w.General[2], next)
	start = next

	return
}