Пример #1
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)
}
Пример #2
0
func loadArray(b *builder, array *ref) (addr, n codegen.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, codegen.Snum(t.N), t.T
	case *types.Slice:
		b.b.Arith(base, nil, "&", array.IR())
		addr = codegen.NewAddrRef(base, 4, 0, false, true)
		n = codegen.NewAddrRef(base, 4, 4, false, true)
		return addr, n, t.T
	}
	panic("bug")
}
Пример #3
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")
}
Пример #4
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, "*", codegen.Snum(arrayElementSize(et)))
	b.b.Arith(addr, base, "+", addr)
	size := et.Size()

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