func (b *builder) buildFunction(fn *Function) {
	if fn.Blocks != nil {
		return // building already started
	}

	var recvField *ast.FieldList
	var body *ast.BlockStmt
	var functype *ast.FuncType
	switch n := fn.syntax.(type) {
	case nil:
		return // not a Go source function.  (Synthetic, or from object file.)
	case *ast.FuncDecl:
		functype = n.Type
		recvField = n.Recv
		body = n.Body
	case *ast.FuncLit:
		functype = n.Type
		body = n.Body
	default:
		panic(n)
	}

	if body == nil {
		// External function.
		if fn.Params == nil {
			// This condition ensures we add a non-empty
			// params list once only, but we may attempt
			// the degenerate empty case repeatedly.
			// TODO(adonovan): opt: don't do that.

			// We set Function.Params even though there is no body
			// code to reference them.  This simplifies clients.
			if recv := fn.Signature.Recv(); recv != nil {
				fn.addParamObj(recv)
			}
			params := fn.Signature.Params()
			for i, n := 0, params.Len(); i < n; i++ {
				fn.addParamObj(params.At(i))
			}
		}
		return
	}
	if fn.Prog.mode&LogSource != 0 {
		defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
	}
	fn.startBody()
	fn.createSyntacticParams(recvField, functype)
	b.stmt(fn, body)
	if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
		// Control fell off the end of the function's body block.
		//
		// Block optimizations eliminate the current block, if
		// unreachable.  It is a builder invariant that
		// if this no-arg return is ill-typed for
		// fn.Signature.Results, this block must be
		// unreachable.  The sanity checker checks this.
		fn.emit(new(RunDefers))
		fn.emit(new(Return))
	}
	fn.finishBody()
}
func (b *builder) buildFunction(fn *Function) {
	if fn.Blocks != nil {
		return 
	}

	var recvField *ast.FieldList
	var body *ast.BlockStmt
	var functype *ast.FuncType
	switch n := fn.syntax.(type) {
	case nil:
		return 
	case *ast.FuncDecl:
		functype = n.Type
		recvField = n.Recv
		body = n.Body
	case *ast.FuncLit:
		functype = n.Type
		body = n.Body
	default:
		panic(n)
	}

	if body == nil {
		
		if fn.Params == nil {
			
			
			
			

			
			
			if recv := fn.Signature.Recv(); recv != nil {
				fn.addParamObj(recv)
			}
			params := fn.Signature.Params()
			for i, n := 0, params.Len(); i < n; i++ {
				fn.addParamObj(params.At(i))
			}
		}
		return
	}
	if fn.Prog.mode&LogSource != 0 {
		defer logStack("build function %s @ %s", fn, fn.Prog.Fset.Position(fn.pos))()
	}
	fn.startBody()
	fn.createSyntacticParams(recvField, functype)
	b.stmt(fn, body)
	if cb := fn.currentBlock; cb != nil && (cb == fn.Blocks[0] || cb == fn.Recover || cb.Preds != nil) {
		
		
		
		
		
		
		
		fn.emit(new(RunDefers))
		fn.emit(new(Return))
	}
	fn.finishBody()
}
func ( b * builder ) buildFunction ( fn * Function ) { if fn . Blocks != nil { return // building already started } var recvField * ast . FieldList var body * ast . BlockStmt var functype * ast . FuncType switch n := fn . syntax . ( type ) { case nil : return // not a Go source function.  (Synthetic, or from object file.) case * ast . FuncDecl : functype = n . Type recvField = n . Recv body = n . Body case * ast . FuncLit : functype = n . Type body = n . Body default : panic ( n ) } if body == nil { // External function. if fn . Params == nil { // This condition ensures we add a non-empty // params list once only, but we may attempt // the degenerate empty case repeatedly. // TODO(adonovan): opt: don't do that. // We set Function.Params even though there is no body // code to reference them.  This simplifies clients. if recv := fn . Signature . Recv ( ) ; recv != nil { fn . addParamObj ( recv ) } params := fn . Signature . Params ( ) for i , n := 0 , params . Len ( ) ; i < n ; i ++ { fn . addParamObj ( params . At ( i ) ) } } return } if fn . Prog . mode & LogSource != 0 { defer logStack ( " " , fn , fn . Prog . Fset . Position ( fn . pos ) ) ( ) } fn . startBody ( ) fn . createSyntacticParams ( recvField , functype ) b . stmt ( fn , body ) if cb := fn . currentBlock ; cb != nil && ( cb == fn . Blocks [ 0 ] || cb == fn . Recover || cb . Preds != nil ) { // Control fell off the end of the function's body block. // // Block optimizations eliminate the current block, if // unreachable.  It is a builder invariant that // if this no-arg return is ill-typed for // fn.Signature.Results, this block must be // unreachable.  The sanity checker checks this. fn . emit ( new ( RunDefers ) ) fn . emit ( new ( Return ) ) } fn . finishBody ( ) }
// buildFunction builds SSA code for the body of function fn.  Idempotent.
buildFunction builds SSA code for the body of function fn . Idempotent .