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 }
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") }
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) }
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") }
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) }