Пример #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)
	}
}
Пример #2
0
func buildIncStmt(b *builder, stmt *tast.IncStmt) {
	expr := b.buildExpr(stmt.Expr)
	switch stmt.Op.Lit {
	case "++":
		b.b.Arith(expr.IR(), expr.IR(), "+", ir.Num(1))
	case "--":
		b.b.Arith(expr.IR(), expr.IR(), "-", ir.Num(1))
	default:
		panic("bug")
	}
}
Пример #3
0
func buildSlicing(b *builder, expr *tast.IndexExpr, array *ref) *ref {
	baseAddr, n, et := loadArray(b, array)

	var addr, indexStart, offset ir.Ref
	if expr.Index == nil {
		indexStart = ir.Num(0)
		addr = baseAddr
	} else {
		indexStart = buildArrayIndex(b, expr.Index)
		checkInRange(b, indexStart, n, "u<=")

		offset = b.newPtr()
		b.b.Arith(offset, indexStart, "*", ir.Snum(arrayElementSize(et)))
		addr = b.newPtr()
		b.b.Arith(addr, baseAddr, "+", offset)
	}

	var indexEnd ir.Ref
	if expr.IndexEnd == nil {
		indexEnd = n
	} else {
		indexEnd = buildArrayIndex(b, expr.IndexEnd)
		checkInRange(b, indexEnd, n, "u<=")
		checkInRange(b, indexStart, indexEnd, "u<=")
	}

	size := b.newPtr()
	b.b.Arith(size, indexEnd, "-", indexStart)
	return newSlice(b, et, addr, size)
}
Пример #4
0
func buildConst(b *builder, c *tast.Const) *ref {
	if _, ok := types.NumConst(c.T); ok {
		// untyped consts are just types.
		return newRef(c.T, nil)
	}

	if t, ok := c.T.(types.Basic); ok {
		v := c.ConstValue.(int64)
		switch t {
		case types.Int, types.Uint:
			return newRef(c.T, ir.Num(uint32(v)))
		case types.Int8, types.Uint8, types.Bool:
			return newRef(c.T, ir.Byt(uint8(v)))
		default:
			panic("other basic types not supported yet")
		}
	}

	if c.T == types.String {
		s := c.ConstValue.(string)
		ret := b.newTemp(c.T)
		b.b.Arith(ret.IR(), nil, "makeStr", b.p.NewString(s))
		return ret
	}

	panic("other const types not supported")
}
Пример #5
0
func binaryOpPtr(b *builder, op string, A, B *ref) *ref {
	atyp := A.Type()
	btyp := B.Type()

	switch op {
	case "==", "!=":
		// replace nil with a typed zero
		if types.IsNil(atyp) {
			A = newRef(btyp, ir.Num(0))
		} else if types.IsNil(btyp) {
			B = newRef(atyp, ir.Num(0))
		}

		ret := b.newTemp(types.Bool)
		b.b.Arith(ret.IR(), A.IR(), op, B.IR())
		return ret
	}
	panic("bug")
}
Пример #6
0
func constNumIr(v int64, t types.T) ir.Ref {
	b, ok := t.(types.Basic)
	if ok {
		switch b {
		case types.Int:
			return ir.Snum(int32(v))
		case types.Uint:
			return ir.Num(uint32(v))
		case types.Int8, types.Uint8:
			return ir.Byt(uint8(v))
		}
	}
	panic("expect an integer type")
}
Пример #7
0
func buildBasicArith(b *builder, ret, A, B *ref, op string) {
	if op == "%" || op == "/" {
		isZero := b.newCond()
		b.b.Arith(isZero, B.IR(), "==", ir.Num(0))

		zeroPanic := b.f.NewBlock(b.b)
		after := b.f.NewBlock(zeroPanic)

		b.b.JumpIfNot(isZero, after)
		b.b = zeroPanic
		callPanic(b, "divided by zero")
		b.b = after
	}

	b.b.Arith(ret.IR(), A.IR(), op, B.IR())
}
Пример #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")
}
Пример #9
0
func buildCast(b *builder, from *ref, t types.T) *ref {
	srcType := from.Type()
	ret := b.newTemp(t)

	if types.IsNil(srcType) {
		size := t.Size()
		if size == arch8.RegSize {
			return newRef(t, ir.Num(0))
		}
		if _, ok := t.(*types.Slice); !ok {
			panic("bug")
		}
		ret := b.newTemp(t)
		b.b.Zero(ret.IR())
		return ret
	}

	if c, ok := srcType.(*types.Const); ok {
		if v, ok := types.NumConst(srcType); ok && types.IsInteger(t) {
			return newRef(t, constNumIr(v, t))
		}
		// TODO: we do not support typed const right?
		// so why need this line?
		srcType = c.Type // using the underlying type
	}

	if types.IsInteger(t) && types.IsInteger(srcType) {
		b.b.Arith(ret.IR(), nil, "cast", from.IR())
		return ret
	}
	if regSizeCastable(t, srcType) {
		b.b.Arith(ret.IR(), nil, "", from.IR())
		return ret
	}
	panic("bug")
}