Beispiel #1
0
func addTestStart(b *builder, testList ir.Ref, n int) {
	b.f = b.p.NewFunc(testStartName, nil, ir.VoidFuncSig)
	b.b = b.f.NewBlock(nil)

	argAddr := ir.Num(arch8.AddrBootArg) // the arg
	index := b.newTempIR(types.Uint)     // to save the index
	b.b.Assign(index, ir.NewAddrRef(argAddr, arch8.RegSize, 0, false, true))

	size := ir.Num(uint32(n))
	checkInRange(b, index, size, "u<")

	base := b.newPtr()
	b.b.Arith(base, nil, "&", testList)
	addr := b.newPtr()
	b.b.Arith(addr, index, "*", ir.Num(arch8.RegSize))
	b.b.Arith(addr, base, "+", addr)

	f := ir.NewFuncPtr(
		ir.VoidFuncSig,
		ir.NewAddrRef(addr, arch8.RegSize, 0, false, true),
	)

	testMain := findFunc(b, "testMain", testMainFuncType)
	if testMain == nil {
		b.b.Call(nil, f)
	} else {
		b.b.Call(nil, testMain.ref.IR(), f)
	}
}
Beispiel #2
0
func newSlice(b *builder, t types.T, addr, size ir.Ref) *ref {
	ret := b.newTemp(&types.Slice{T: t})
	retAddr := b.newPtr()
	b.b.Arith(retAddr, nil, "&", ret.IR())
	b.b.Assign(ir.NewAddrRef(retAddr, 4, 0, false, true), addr)
	b.b.Assign(ir.NewAddrRef(retAddr, 4, 4, false, true), size)
	return ret
}
Beispiel #3
0
func loadArray(b *builder, array *ref) (addr, n ir.Ref, et types.T) {
	base := b.newPtr()
	t := array.Type()
	switch t := t.(type) {
	case *types.Array:
		b.b.Arith(base, nil, "&", array.IR())
		return base, ir.Snum(t.N), t.T
	case *types.Slice:
		b.b.Arith(base, nil, "&", array.IR())
		addr = ir.NewAddrRef(base, 4, 0, false, true)
		n = ir.NewAddrRef(base, 4, 4, false, true)
		return addr, n, t.T
	}
	panic("bug")
}
Beispiel #4
0
func testNilSlice(b *builder, r *ref, neg bool) *ref {
	addr := b.newPtr()
	isNil := b.newCond()
	b.b.Arith(addr, nil, "&", r.IR())
	b.b.Arith(isNil, nil, "?", ir.NewAddrRef(addr, 4, 0, false, true))
	if neg {
		b.b.Arith(isNil, nil, "!", isNil)
	}
	return newRef(types.Bool, isNil)
}
Beispiel #5
0
func buildField(b *builder, this ir.Ref, field *types.Field) *ref {
	retIR := ir.NewAddrRef(
		this,
		field.T.Size(),
		field.Offset(),
		types.IsByte(field.T),
		true,
	)
	return newAddressableRef(field.T, retIR)
}
Beispiel #6
0
func buildStarExpr(b *builder, expr *tast.StarExpr) *ref {
	addr := b.buildExpr(expr.Expr)
	nilPointerPanic(b, addr.IR())
	t := addr.Type().(*types.Pointer).T
	retIR := ir.NewAddrRef(
		addr.IR(), // base
		t.Size(),  // size
		0,         // offset
		types.IsBasic(t, types.Uint8), // is byte?
		t.RegSizeAlign(),              // is aligned?
	)
	return newAddressableRef(t, retIR)
}
Beispiel #7
0
func binaryOpSlice(b *builder, op string, A, B *ref) *ref {
	atyp := A.Type()
	btyp := B.Type()

	switch op {
	case "==", "!=":
		if types.IsNil(atyp) {
			return testNilSlice(b, B, op == "==")
		} else if types.IsNil(btyp) {
			return testNilSlice(b, A, op == "==")
		}

		addrA := b.newPtr()
		addrB := b.newPtr()
		b.b.Arith(addrA, nil, "&", A.IR())
		b.b.Arith(addrB, nil, "&", B.IR())
		baseA := ir.NewAddrRef(addrA, 4, 0, false, true)
		sizeA := ir.NewAddrRef(addrA, 4, 4, false, true)
		baseB := ir.NewAddrRef(addrB, 4, 0, false, true)
		sizeB := ir.NewAddrRef(addrB, 4, 4, false, true)

		ptrEq := b.newCond()
		sizeEq := b.newCond()

		b.b.Arith(ptrEq, baseA, "==", baseB)
		b.b.Arith(sizeEq, sizeA, "==", sizeB)

		ret := b.newCond()
		b.b.Arith(ret, ptrEq, "&", sizeEq)
		if op == "!=" {
			b.b.Arith(ret, nil, "!", ret)
		}
		return newRef(types.Bool, ret)
	}
	panic("bug")
}
Beispiel #8
0
func buildCallLen(b *builder, expr *tast.CallExpr) *ref {
	args := b.buildExpr(expr.Args)
	t := args.Type()
	ret := b.newTemp(types.Int)
	switch t := t.(type) {
	case *types.Slice:
		addr := b.newPtr()
		b.b.Arith(addr, nil, "&", args.IR())
		b.b.Assign(ret.IR(), ir.NewAddrRef(addr, 4, 4, false, true))
		return ret
	case *types.Array:
		b.b.Assign(ret.IR(), ir.Num(uint32(t.N)))
		return ret
	}
	panic("bug")
}
Beispiel #9
0
func buildArrayGet(b *builder, expr *tast.IndexExpr, array *ref) *ref {
	index := buildArrayIndex(b, expr.Index)
	base, n, et := loadArray(b, array)
	checkInRange(b, index, n, "u<")

	addr := b.newPtr()
	b.b.Arith(addr, index, "*", ir.Snum(arrayElementSize(et)))
	b.b.Arith(addr, base, "+", addr)
	size := et.Size()

	retIR := ir.NewAddrRef(
		addr,             // base address
		size,             // size
		0,                // dynamic offset; precalculated
		types.IsByte(et), // isByte
		true,             // isAlign
	)
	return newAddressableRef(et, retIR)
}