_linters/src/honnef.co/go/tools/ssa/builder.go
func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
	switch obj.Name() {
	case "make":
		switch typ.Underlying().(type) {
		case *types.Slice:
			n := b.expr(fn, args[1])
			m := n
			if len(args) == 3 {
				m = b.expr(fn, args[2])
			}
			if m, ok := m.(*Const); ok {
				// treat make([]T, n, m) as new([m]T)[:n]
				cap := m.Int64()
				at := types.NewArray(typ.Underlying().(*types.Slice).Elem(), cap)
				alloc := emitNew(fn, at, pos)
				alloc.Comment = "makeslice"
				v := &Slice{
					X:    alloc,
					High: n,
				}
				v.setPos(pos)
				v.setType(typ)
				return fn.emit(v)
			}
			v := &MakeSlice{
				Len: n,
				Cap: m,
			}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)

		case *types.Map:
			var res Value
			if len(args) == 2 {
				res = b.expr(fn, args[1])
			}
			v := &MakeMap{Reserve: res}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)

		case *types.Chan:
			var sz Value = vZero
			if len(args) == 2 {
				sz = b.expr(fn, args[1])
			}
			v := &MakeChan{Size: sz}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)
		}

	case "new":
		alloc := emitNew(fn, deref(typ), pos)
		alloc.Comment = "new"
		return alloc

	case "len", "cap":
		// Special case: len or cap of an array or *array is
		// based on the type, not the value which may be nil.
		// We must still evaluate the value, though.  (If it
		// was side-effect free, the whole call would have
		// been constant-folded.)
		t := deref(fn.Pkg.typeOf(args[0])).Underlying()
		if at, ok := t.(*types.Array); ok {
			b.expr(fn, args[0]) // for effects only
			return intConst(at.Len())
		}
		// Otherwise treat as normal.

	case "panic":
		fn.emit(&Panic{
			X:   emitConv(fn, b.expr(fn, args[0]), tEface),
			pos: pos,
		})
		fn.currentBlock = fn.newBasicBlock("unreachable")
		return vTrue // any non-nil Value will do
	}
	return nil // treat all others as a regular function call
}
func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
	switch obj.Name() {
	case "make":
		switch typ.Underlying().(type) {
		case *types.Slice:
			n := b.expr(fn, args[1])
			m := n
			if len(args) == 3 {
				m = b.expr(fn, args[2])
			}
			if m, ok := m.(*Const); ok {
				// treat make([]T, n, m) as new([m]T)[:n]
				cap := m.Int64()
				at := types.NewArray(typ.Underlying().(*types.Slice).Elem(), cap)
				alloc := emitNew(fn, at, pos)
				alloc.Comment = "makeslice"
				v := &Slice{
					X:    alloc,
					High: n,
				}
				v.setPos(pos)
				v.setType(typ)
				return fn.emit(v)
			}
			v := &MakeSlice{
				Len: n,
				Cap: m,
			}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)

		case *types.Map:
			var res Value
			if len(args) == 2 {
				res = b.expr(fn, args[1])
			}
			v := &MakeMap{Reserve: res}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)

		case *types.Chan:
			var sz Value = vZero
			if len(args) == 2 {
				sz = b.expr(fn, args[1])
			}
			v := &MakeChan{Size: sz}
			v.setPos(pos)
			v.setType(typ)
			return fn.emit(v)
		}

	case "new":
		alloc := emitNew(fn, deref(typ), pos)
		alloc.Comment = "new"
		return alloc

	case "len", "cap":
		// Special case: len or cap of an array or *array is
		// based on the type, not the value which may be nil.
		// We must still evaluate the value, though.  (If it
		// was side-effect free, the whole call would have
		// been constant-folded.)
		t := deref(fn.Pkg.typeOf(args[0])).Underlying()
		if at, ok := t.(*types.Array); ok {
			b.expr(fn, args[0]) // for effects only
			return intConst(at.Len())
		}
		// Otherwise treat as normal.

	case "panic":
		fn.emit(&Panic{
			X:   emitConv(fn, b.expr(fn, args[0]), tEface),
			pos: pos,
		})
		fn.currentBlock = fn.newBasicBlock("unreachable")
		return vTrue // any non-nil Value will do
	}
	return nil // treat all others as a regular function call
}
func ( b * builder ) builtin ( fn * Function , obj * types . Builtin , args [ ] ast . Expr , typ types . Type , pos token . Pos ) Value { switch obj . Name ( ) { case " " : switch typ . Underlying ( ) . ( type ) { case * types . Slice : n := b . expr ( fn , args [ 1 ] ) m := n if len ( args ) == 3 { m = b . expr ( fn , args [ 2 ] ) } if m , ok := m . ( * Const ) ; ok { // treat make([]T, n, m) as new([m]T)[:n] cap := m . Int64 ( ) at := types . NewArray ( typ . Underlying ( ) . ( * types . Slice ) . Elem ( ) , cap ) alloc := emitNew ( fn , at , pos ) alloc . Comment = " " v := & Slice { X : alloc , High : n , } v . setPos ( pos ) v . setType ( typ ) return fn . emit ( v ) } v := & MakeSlice { Len : n , Cap : m , } v . setPos ( pos ) v . setType ( typ ) return fn . emit ( v ) case * types . Map : var res Value if len ( args ) == 2 { res = b . expr ( fn , args [ 1 ] ) } v := & MakeMap { Reserve : res } v . setPos ( pos ) v . setType ( typ ) return fn . emit ( v ) case * types . Chan : var sz Value = vZero if len ( args ) == 2 { sz = b . expr ( fn , args [ 1 ] ) } v := & MakeChan { Size : sz } v . setPos ( pos ) v . setType ( typ ) return fn . emit ( v ) } case " " : alloc := emitNew ( fn , deref ( typ ) , pos ) alloc . Comment = " " return alloc case " " , " " : // Special case: len or cap of an array or *array is // based on the type, not the value which may be nil. // We must still evaluate the value, though.  (If it // was side-effect free, the whole call would have // been constant-folded.) t := deref ( fn . Pkg . typeOf ( args [ 0 ] ) ) . Underlying ( ) if at , ok := t . ( * types . Array ) ; ok { b . expr ( fn , args [ 0 ] ) // for effects only return intConst ( at . Len ( ) ) } // Otherwise treat as normal. case " " : fn . emit ( & Panic { X : emitConv ( fn , b . expr ( fn , args [ 0 ] ) , tEface ) , pos : pos , } ) fn . currentBlock = fn . newBasicBlock ( " " ) return vTrue // any non-nil Value will do } return nil // treat all others as a regular function call }
// builtin emits to fn SSA instructions to implement a call to the
// built-in function obj with the specified arguments
// and return type.  It returns the value defined by the result.
//
// The result is nil if no special handling was required; in this case
// the caller should treat this like an ordinary library function
// call.
//
builtin emits to fn SSA instructions to implement a call to the built - in function obj with the specified arguments and return type . It returns the value defined by the result . The result is nil if no special handling was required ; in this case the caller should treat this like an ordinary library function call .