Ejemplo n.º 1
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(), "+", codegen.Num(1))
	case "--":
		b.b.Arith(expr.IR(), expr.IR(), "-", codegen.Num(1))
	default:
		panic("bug")
	}
}
Ejemplo n.º 2
0
func buildSlicing(b *builder, expr *tast.IndexExpr, array *ref) *ref {
	baseAddr, n, et := loadArray(b, array)

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

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

	var indexEnd codegen.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)
}
Ejemplo n.º 3
0
Archivo: call.go Proyecto: Xslxy/e8vm
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(), codegen.NewAddrRef(addr, 4, 4, false, true))
		return ret
	case *types.Array:
		b.b.Assign(ret.IR(), codegen.Num(uint32(t.N)))
		return ret
	}
	panic("bug")
}
Ejemplo n.º 4
0
func constNumIr(v int64, t types.T) codegen.Ref {
	b, ok := t.(types.Basic)
	if ok {
		switch b {
		case types.Int:
			return codegen.Snum(int32(v))
		case types.Uint:
			return codegen.Num(uint32(v))
		case types.Int8:
			return codegen.Byt(uint8(v), false)
		case types.Uint8:
			return codegen.Byt(uint8(v), true)
		}
	}
	panic("expect an integer type")
}
Ejemplo n.º 5
0
func buildBasicArith(b *builder, ret, A, B *ref, op string) {
	switch op {
	case "/", "%", "u/", "u%":
		isZero := b.newCond()
		b.b.Arith(isZero, B.IR(), "==", codegen.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())
}
Ejemplo n.º 6
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, codegen.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")
}