_linters/src/honnef.co/go/tools/ssa/builder.go
func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
	// f(x, y, z...): pass slice z straight through.
	if e.Ellipsis != 0 {
		for i, arg := range e.Args {
			v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
			args = append(args, v)
		}
		return args
	}

	offset := len(args) // 1 if call has receiver, 0 otherwise

	// Evaluate actual parameter expressions.
	//
	// If this is a chained call of the form f(g()) where g has
	// multiple return values (MRV), they are flattened out into
	// args; a suffix of them may end up in a varargs slice.
	for _, arg := range e.Args {
		v := b.expr(fn, arg)
		if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain
			for i, n := 0, ttuple.Len(); i < n; i++ {
				args = append(args, emitExtract(fn, v, i))
			}
		} else {
			args = append(args, v)
		}
	}

	// Actual->formal assignability conversions for normal parameters.
	np := sig.Params().Len() // number of normal parameters
	if sig.Variadic() {
		np--
	}
	for i := 0; i < np; i++ {
		args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
	}

	// Actual->formal assignability conversions for variadic parameter,
	// and construction of slice.
	if sig.Variadic() {
		varargs := args[offset+np:]
		st := sig.Params().At(np).Type().(*types.Slice)
		vt := st.Elem()
		if len(varargs) == 0 {
			args = append(args, nilConst(st))
		} else {
			// Replace a suffix of args with a slice containing it.
			at := types.NewArray(vt, int64(len(varargs)))
			a := emitNew(fn, at, token.NoPos)
			a.setPos(e.Rparen)
			a.Comment = "varargs"
			for i, arg := range varargs {
				iaddr := &IndexAddr{
					X:     a,
					Index: intConst(int64(i)),
				}
				iaddr.setType(types.NewPointer(vt))
				fn.emit(iaddr)
				emitStore(fn, iaddr, arg, arg.Pos())
			}
			s := &Slice{X: a}
			s.setType(st)
			args[offset+np] = fn.emit(s)
			args = args[:offset+np+1]
		}
	}
	return args
}
func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
	// f(x, y, z...): pass slice z straight through.
	if e.Ellipsis != 0 {
		for i, arg := range e.Args {
			v := emitConv(fn, b.expr(fn, arg), sig.Params().At(i).Type())
			args = append(args, v)
		}
		return args
	}

	offset := len(args) // 1 if call has receiver, 0 otherwise

	// Evaluate actual parameter expressions.
	//
	// If this is a chained call of the form f(g()) where g has
	// multiple return values (MRV), they are flattened out into
	// args; a suffix of them may end up in a varargs slice.
	for _, arg := range e.Args {
		v := b.expr(fn, arg)
		if ttuple, ok := v.Type().(*types.Tuple); ok { // MRV chain
			for i, n := 0, ttuple.Len(); i < n; i++ {
				args = append(args, emitExtract(fn, v, i))
			}
		} else {
			args = append(args, v)
		}
	}

	// Actual->formal assignability conversions for normal parameters.
	np := sig.Params().Len() // number of normal parameters
	if sig.Variadic() {
		np--
	}
	for i := 0; i < np; i++ {
		args[offset+i] = emitConv(fn, args[offset+i], sig.Params().At(i).Type())
	}

	// Actual->formal assignability conversions for variadic parameter,
	// and construction of slice.
	if sig.Variadic() {
		varargs := args[offset+np:]
		st := sig.Params().At(np).Type().(*types.Slice)
		vt := st.Elem()
		if len(varargs) == 0 {
			args = append(args, nilConst(st))
		} else {
			// Replace a suffix of args with a slice containing it.
			at := types.NewArray(vt, int64(len(varargs)))
			a := emitNew(fn, at, token.NoPos)
			a.setPos(e.Rparen)
			a.Comment = "varargs"
			for i, arg := range varargs {
				iaddr := &IndexAddr{
					X:     a,
					Index: intConst(int64(i)),
				}
				iaddr.setType(types.NewPointer(vt))
				fn.emit(iaddr)
				emitStore(fn, iaddr, arg, arg.Pos())
			}
			s := &Slice{X: a}
			s.setType(st)
			args[offset+np] = fn.emit(s)
			args = args[:offset+np+1]
		}
	}
	return args
}
func ( b * builder ) emitCallArgs ( fn * Function , sig * types . Signature , e * ast . CallExpr , args [ ] Value ) [ ] Value { // f(x, y, z...): pass slice z straight through. if e . Ellipsis != 0 { for i , arg := range e . Args { v := emitConv ( fn , b . expr ( fn , arg ) , sig . Params ( ) . At ( i ) . Type ( ) ) args = append ( args , v ) } return args } offset := len ( args ) // 1 if call has receiver, 0 otherwise // Evaluate actual parameter expressions. // // If this is a chained call of the form f(g()) where g has // multiple return values (MRV), they are flattened out into // args; a suffix of them may end up in a varargs slice. for _ , arg := range e . Args { v := b . expr ( fn , arg ) if ttuple , ok := v . Type ( ) . ( * types . Tuple ) ; ok { // MRV chain for i , n := 0 , ttuple . Len ( ) ; i < n ; i ++ { args = append ( args , emitExtract ( fn , v , i ) ) } } else { args = append ( args , v ) } } // Actual->formal assignability conversions for normal parameters. np := sig . Params ( ) . Len ( ) // number of normal parameters if sig . Variadic ( ) { np -- } for i := 0 ; i < np ; i ++ { args [ offset + i ] = emitConv ( fn , args [ offset + i ] , sig . Params ( ) . At ( i ) . Type ( ) ) } // Actual->formal assignability conversions for variadic parameter, // and construction of slice. if sig . Variadic ( ) { varargs := args [ offset + np : ] st := sig . Params ( ) . At ( np ) . Type ( ) . ( * types . Slice ) vt := st . Elem ( ) if len ( varargs ) == 0 { args = append ( args , nilConst ( st ) ) } else { // Replace a suffix of args with a slice containing it. at := types . NewArray ( vt , int64 ( len ( varargs ) ) ) a := emitNew ( fn , at , token . NoPos ) a . setPos ( e . Rparen ) a . Comment = " " for i , arg := range varargs { iaddr := & IndexAddr { X : a , Index : intConst ( int64 ( i ) ) , } iaddr . setType ( types . NewPointer ( vt ) ) fn . emit ( iaddr ) emitStore ( fn , iaddr , arg , arg . Pos ( ) ) } s := & Slice { X : a } s . setType ( st ) args [ offset + np ] = fn . emit ( s ) args = args [ : offset + np + 1 ] } } return args }
// emitCallArgs emits to f code for the actual parameters of call e to
// a (possibly built-in) function of effective type sig.
// The argument values are appended to args, which is then returned.
//
emitCallArgs emits to f code for the actual parameters of call e to a ( possibly built - in ) function of effective type sig . The argument values are appended to args which is then returned .