func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
	//
	//      length = len(x)
	//      index = -1
	// loop:                                   (target of continue)
	//      index++
	// 	if index < length goto body else done
	// body:
	//      k = index
	//      v = x[index]
	//      ...body...
	// 	jump loop
	// done:                                   (target of break)

	// Determine number of iterations.
	var length Value
	if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
		// For array or *array, the number of iterations is
		// known statically thanks to the type.  We avoid a
		// data dependence upon x, permitting later dead-code
		// elimination if x is pure, static unrolling, etc.
		// Ranging over a nil *array may have >0 iterations.
		// We still generate code for x, in case it has effects.
		length = intConst(arr.Len())
	} else {
		// length = len(x).
		var c Call
		c.Call.Value = makeLen(x.Type())
		c.Call.Args = []Value{x}
		c.setType(tInt)
		length = fn.emit(&c)
	}

	index := fn.addLocal(tInt, token.NoPos)
	emitStore(fn, index, intConst(-1), pos)

	loop = fn.newBasicBlock("rangeindex.loop")
	emitJump(fn, loop)
	fn.currentBlock = loop

	incr := &BinOp{
		Op: token.ADD,
		X:  emitLoad(fn, index),
		Y:  vOne,
	}
	incr.setType(tInt)
	emitStore(fn, index, fn.emit(incr), pos)

	body := fn.newBasicBlock("rangeindex.body")
	done = fn.newBasicBlock("rangeindex.done")
	emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
	fn.currentBlock = body

	k = emitLoad(fn, index)
	if tv != nil {
		switch t := x.Type().Underlying().(type) {
		case *types.Array:
			instr := &Index{
				X:     x,
				Index: k,
			}
			instr.setType(t.Elem())
			v = fn.emit(instr)

		case *types.Pointer: // *array
			instr := &IndexAddr{
				X:     x,
				Index: k,
			}
			instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
			v = emitLoad(fn, fn.emit(instr))

		case *types.Slice:
			instr := &IndexAddr{
				X:     x,
				Index: k,
			}
			instr.setType(types.NewPointer(t.Elem()))
			v = emitLoad(fn, fn.emit(instr))

		default:
			panic("rangeIndexed x:" + t.String())
		}
	}
	return
}
func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
	
	
	
	
	
	
	
	
	
	
	
	

	
	var length Value
	if arr, ok := deref(x.Type()).Underlying().(*types.Array); ok {
		
		
		
		
		
		
		length = intConst(arr.Len())
	} else {
		
		var c Call
		c.Call.Value = makeLen(x.Type())
		c.Call.Args = []Value{x}
		c.setType(tInt)
		length = fn.emit(&c)
	}

	index := fn.addLocal(tInt, token.NoPos)
	emitStore(fn, index, intConst(-1), pos)

	loop = fn.newBasicBlock("rangeindex.loop")
	emitJump(fn, loop)
	fn.currentBlock = loop

	incr := &BinOp{
		Op: token.ADD,
		X:  emitLoad(fn, index),
		Y:  vOne,
	}
	incr.setType(tInt)
	emitStore(fn, index, fn.emit(incr), pos)

	body := fn.newBasicBlock("rangeindex.body")
	done = fn.newBasicBlock("rangeindex.done")
	emitIf(fn, emitCompare(fn, token.LSS, incr, length, token.NoPos), body, done)
	fn.currentBlock = body

	k = emitLoad(fn, index)
	if tv != nil {
		switch t := x.Type().Underlying().(type) {
		case *types.Array:
			instr := &Index{
				X:     x,
				Index: k,
			}
			instr.setType(t.Elem())
			v = fn.emit(instr)

		case *types.Pointer: 
			instr := &IndexAddr{
				X:     x,
				Index: k,
			}
			instr.setType(types.NewPointer(t.Elem().Underlying().(*types.Array).Elem()))
			v = emitLoad(fn, fn.emit(instr))

		case *types.Slice:
			instr := &IndexAddr{
				X:     x,
				Index: k,
			}
			instr.setType(types.NewPointer(t.Elem()))
			v = emitLoad(fn, fn.emit(instr))

		default:
			panic("rangeIndexed x:" + t.String())
		}
	}
	return
}
func ( b * builder ) rangeIndexed ( fn * Function , x Value , tv types . Type , pos token . Pos ) ( k , v Value , loop , done * BasicBlock ) { // //      length = len(x) //      index = -1 // loop:                                   (target of continue) //      index++ // 	if index < length goto body else done // body: //      k = index //      v = x[index] //      ...body... // 	jump loop // done:                                   (target of break) // Determine number of iterations. var length Value if arr , ok := deref ( x . Type ( ) ) . Underlying ( ) . ( * types . Array ) ; ok { // For array or *array, the number of iterations is // known statically thanks to the type.  We avoid a // data dependence upon x, permitting later dead-code // elimination if x is pure, static unrolling, etc. // Ranging over a nil *array may have >0 iterations. // We still generate code for x, in case it has effects. length = intConst ( arr . Len ( ) ) } else { // length = len(x). var c Call c . Call . Value = makeLen ( x . Type ( ) ) c . Call . Args = [ ] Value { x } c . setType ( tInt ) length = fn . emit ( & c ) } index := fn . addLocal ( tInt , token . NoPos ) emitStore ( fn , index , intConst ( - 1 ) , pos ) loop = fn . newBasicBlock ( " " ) emitJump ( fn , loop ) fn . currentBlock = loop incr := & BinOp { Op : token . ADD , X : emitLoad ( fn , index ) , Y : vOne , } incr . setType ( tInt ) emitStore ( fn , index , fn . emit ( incr ) , pos ) body := fn . newBasicBlock ( " " ) done = fn . newBasicBlock ( " " ) emitIf ( fn , emitCompare ( fn , token . LSS , incr , length , token . NoPos ) , body , done ) fn . currentBlock = body k = emitLoad ( fn , index ) if tv != nil { switch t := x . Type ( ) . Underlying ( ) . ( type ) { case * types . Array : instr := & Index { X : x , Index : k , } instr . setType ( t . Elem ( ) ) v = fn . emit ( instr ) case * types . Pointer : // *array instr := & IndexAddr { X : x , Index : k , } instr . setType ( types . NewPointer ( t . Elem ( ) . Underlying ( ) . ( * types . Array ) . Elem ( ) ) ) v = emitLoad ( fn , fn . emit ( instr ) ) case * types . Slice : instr := & IndexAddr { X : x , Index : k , } instr . setType ( types . NewPointer ( t . Elem ( ) ) ) v = emitLoad ( fn , fn . emit ( instr ) ) default : panic ( " " + t . String ( ) ) } } return }
// rangeIndexed emits to fn the header for an integer-indexed loop
// over array, *array or slice value x.
// The v result is defined only if tv is non-nil.
// forPos is the position of the "for" token.
//
rangeIndexed emits to fn the header for an integer - indexed loop over array * array or slice value x . The v result is defined only if tv is non - nil . forPos is the position of the for token .