Beispiel #1
0
func newSlice(b *builder, t types.T, addr, size codegen.Ref) *ref {
	ret := b.newTemp(&types.Slice{T: t})
	retAddr := b.newPtr()
	b.b.Arith(retAddr, nil, "&", ret.IR())
	b.b.Assign(codegen.NewAddrRef(retAddr, 4, 0, false, true), addr)
	b.b.Assign(codegen.NewAddrRef(retAddr, 4, 4, false, true), size)
	return ret
}
Beispiel #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")
}
Beispiel #3
0
func buildField(b *builder, this codegen.Ref, field *types.Field) *ref {
	retIR := codegen.NewAddrRef(
		this,
		field.T.Size(),
		field.Offset(),
		types.IsByte(field.T),
		true,
	)
	return newAddressableRef(field.T, retIR)
}
Beispiel #4
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(), 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")
}
Beispiel #5
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)
}