1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ssagen
6
7import (
8	"bufio"
9	"bytes"
10	"fmt"
11	"go/constant"
12	"html"
13	"internal/buildcfg"
14	"os"
15	"path/filepath"
16	"sort"
17	"strings"
18
19	"cmd/compile/internal/abi"
20	"cmd/compile/internal/base"
21	"cmd/compile/internal/ir"
22	"cmd/compile/internal/liveness"
23	"cmd/compile/internal/objw"
24	"cmd/compile/internal/reflectdata"
25	"cmd/compile/internal/rttype"
26	"cmd/compile/internal/ssa"
27	"cmd/compile/internal/staticdata"
28	"cmd/compile/internal/typecheck"
29	"cmd/compile/internal/types"
30	"cmd/internal/obj"
31	"cmd/internal/objabi"
32	"cmd/internal/src"
33	"cmd/internal/sys"
34
35	rtabi "internal/abi"
36)
37
38var ssaConfig *ssa.Config
39var ssaCaches []ssa.Cache
40
41var ssaDump string     // early copy of $GOSSAFUNC; the func name to dump output for
42var ssaDir string      // optional destination for ssa dump file
43var ssaDumpStdout bool // whether to dump to stdout
44var ssaDumpCFG string  // generate CFGs for these phases
45const ssaDumpFile = "ssa.html"
46
47// ssaDumpInlined holds all inlined functions when ssaDump contains a function name.
48var ssaDumpInlined []*ir.Func
49
50func DumpInline(fn *ir.Func) {
51	if ssaDump != "" && ssaDump == ir.FuncName(fn) {
52		ssaDumpInlined = append(ssaDumpInlined, fn)
53	}
54}
55
56func InitEnv() {
57	ssaDump = os.Getenv("GOSSAFUNC")
58	ssaDir = os.Getenv("GOSSADIR")
59	if ssaDump != "" {
60		if strings.HasSuffix(ssaDump, "+") {
61			ssaDump = ssaDump[:len(ssaDump)-1]
62			ssaDumpStdout = true
63		}
64		spl := strings.Split(ssaDump, ":")
65		if len(spl) > 1 {
66			ssaDump = spl[0]
67			ssaDumpCFG = spl[1]
68		}
69	}
70}
71
72func InitConfig() {
73	types_ := ssa.NewTypes()
74
75	if Arch.SoftFloat {
76		softfloatInit()
77	}
78
79	// Generate a few pointer types that are uncommon in the frontend but common in the backend.
80	// Caching is disabled in the backend, so generating these here avoids allocations.
81	_ = types.NewPtr(types.Types[types.TINTER])                             // *interface{}
82	_ = types.NewPtr(types.NewPtr(types.Types[types.TSTRING]))              // **string
83	_ = types.NewPtr(types.NewSlice(types.Types[types.TINTER]))             // *[]interface{}
84	_ = types.NewPtr(types.NewPtr(types.ByteType))                          // **byte
85	_ = types.NewPtr(types.NewSlice(types.ByteType))                        // *[]byte
86	_ = types.NewPtr(types.NewSlice(types.Types[types.TSTRING]))            // *[]string
87	_ = types.NewPtr(types.NewPtr(types.NewPtr(types.Types[types.TUINT8]))) // ***uint8
88	_ = types.NewPtr(types.Types[types.TINT16])                             // *int16
89	_ = types.NewPtr(types.Types[types.TINT64])                             // *int64
90	_ = types.NewPtr(types.ErrorType)                                       // *error
91	_ = types.NewPtr(reflectdata.MapType())                                 // *runtime.hmap
92	_ = types.NewPtr(deferstruct())                                         // *runtime._defer
93	types.NewPtrCacheEnabled = false
94	ssaConfig = ssa.NewConfig(base.Ctxt.Arch.Name, *types_, base.Ctxt, base.Flag.N == 0, Arch.SoftFloat)
95	ssaConfig.Race = base.Flag.Race
96	ssaCaches = make([]ssa.Cache, base.Flag.LowerC)
97
98	// Set up some runtime functions we'll need to call.
99	ir.Syms.AssertE2I = typecheck.LookupRuntimeFunc("assertE2I")
100	ir.Syms.AssertE2I2 = typecheck.LookupRuntimeFunc("assertE2I2")
101	ir.Syms.AssertI2I = typecheck.LookupRuntimeFunc("assertI2I")
102	ir.Syms.AssertI2I2 = typecheck.LookupRuntimeFunc("assertI2I2")
103	ir.Syms.CgoCheckMemmove = typecheck.LookupRuntimeFunc("cgoCheckMemmove")
104	ir.Syms.CgoCheckPtrWrite = typecheck.LookupRuntimeFunc("cgoCheckPtrWrite")
105	ir.Syms.CheckPtrAlignment = typecheck.LookupRuntimeFunc("checkptrAlignment")
106	ir.Syms.Deferproc = typecheck.LookupRuntimeFunc("deferproc")
107	ir.Syms.Deferprocat = typecheck.LookupRuntimeFunc("deferprocat")
108	ir.Syms.DeferprocStack = typecheck.LookupRuntimeFunc("deferprocStack")
109	ir.Syms.Deferreturn = typecheck.LookupRuntimeFunc("deferreturn")
110	ir.Syms.Duffcopy = typecheck.LookupRuntimeFunc("duffcopy")
111	ir.Syms.Duffzero = typecheck.LookupRuntimeFunc("duffzero")
112	ir.Syms.GCWriteBarrier[0] = typecheck.LookupRuntimeFunc("gcWriteBarrier1")
113	ir.Syms.GCWriteBarrier[1] = typecheck.LookupRuntimeFunc("gcWriteBarrier2")
114	ir.Syms.GCWriteBarrier[2] = typecheck.LookupRuntimeFunc("gcWriteBarrier3")
115	ir.Syms.GCWriteBarrier[3] = typecheck.LookupRuntimeFunc("gcWriteBarrier4")
116	ir.Syms.GCWriteBarrier[4] = typecheck.LookupRuntimeFunc("gcWriteBarrier5")
117	ir.Syms.GCWriteBarrier[5] = typecheck.LookupRuntimeFunc("gcWriteBarrier6")
118	ir.Syms.GCWriteBarrier[6] = typecheck.LookupRuntimeFunc("gcWriteBarrier7")
119	ir.Syms.GCWriteBarrier[7] = typecheck.LookupRuntimeFunc("gcWriteBarrier8")
120	ir.Syms.Goschedguarded = typecheck.LookupRuntimeFunc("goschedguarded")
121	ir.Syms.Growslice = typecheck.LookupRuntimeFunc("growslice")
122	ir.Syms.InterfaceSwitch = typecheck.LookupRuntimeFunc("interfaceSwitch")
123	ir.Syms.Memmove = typecheck.LookupRuntimeFunc("memmove")
124	ir.Syms.Msanread = typecheck.LookupRuntimeFunc("msanread")
125	ir.Syms.Msanwrite = typecheck.LookupRuntimeFunc("msanwrite")
126	ir.Syms.Msanmove = typecheck.LookupRuntimeFunc("msanmove")
127	ir.Syms.Asanread = typecheck.LookupRuntimeFunc("asanread")
128	ir.Syms.Asanwrite = typecheck.LookupRuntimeFunc("asanwrite")
129	ir.Syms.Newobject = typecheck.LookupRuntimeFunc("newobject")
130	ir.Syms.Newproc = typecheck.LookupRuntimeFunc("newproc")
131	ir.Syms.Panicdivide = typecheck.LookupRuntimeFunc("panicdivide")
132	ir.Syms.PanicdottypeE = typecheck.LookupRuntimeFunc("panicdottypeE")
133	ir.Syms.PanicdottypeI = typecheck.LookupRuntimeFunc("panicdottypeI")
134	ir.Syms.Panicnildottype = typecheck.LookupRuntimeFunc("panicnildottype")
135	ir.Syms.Panicoverflow = typecheck.LookupRuntimeFunc("panicoverflow")
136	ir.Syms.Panicshift = typecheck.LookupRuntimeFunc("panicshift")
137	ir.Syms.Racefuncenter = typecheck.LookupRuntimeFunc("racefuncenter")
138	ir.Syms.Racefuncexit = typecheck.LookupRuntimeFunc("racefuncexit")
139	ir.Syms.Raceread = typecheck.LookupRuntimeFunc("raceread")
140	ir.Syms.Racereadrange = typecheck.LookupRuntimeFunc("racereadrange")
141	ir.Syms.Racewrite = typecheck.LookupRuntimeFunc("racewrite")
142	ir.Syms.Racewriterange = typecheck.LookupRuntimeFunc("racewriterange")
143	ir.Syms.TypeAssert = typecheck.LookupRuntimeFunc("typeAssert")
144	ir.Syms.WBZero = typecheck.LookupRuntimeFunc("wbZero")
145	ir.Syms.WBMove = typecheck.LookupRuntimeFunc("wbMove")
146	ir.Syms.X86HasPOPCNT = typecheck.LookupRuntimeVar("x86HasPOPCNT")       // bool
147	ir.Syms.X86HasSSE41 = typecheck.LookupRuntimeVar("x86HasSSE41")         // bool
148	ir.Syms.X86HasFMA = typecheck.LookupRuntimeVar("x86HasFMA")             // bool
149	ir.Syms.ARMHasVFPv4 = typecheck.LookupRuntimeVar("armHasVFPv4")         // bool
150	ir.Syms.ARM64HasATOMICS = typecheck.LookupRuntimeVar("arm64HasATOMICS") // bool
151	ir.Syms.Staticuint64s = typecheck.LookupRuntimeVar("staticuint64s")
152	ir.Syms.Typedmemmove = typecheck.LookupRuntimeFunc("typedmemmove")
153	ir.Syms.Udiv = typecheck.LookupRuntimeVar("udiv")                 // asm func with special ABI
154	ir.Syms.WriteBarrier = typecheck.LookupRuntimeVar("writeBarrier") // struct { bool; ... }
155	ir.Syms.Zerobase = typecheck.LookupRuntimeVar("zerobase")
156
157	if Arch.LinkArch.Family == sys.Wasm {
158		BoundsCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeFunc("goPanicIndex")
159		BoundsCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeFunc("goPanicIndexU")
160		BoundsCheckFunc[ssa.BoundsSliceAlen] = typecheck.LookupRuntimeFunc("goPanicSliceAlen")
161		BoundsCheckFunc[ssa.BoundsSliceAlenU] = typecheck.LookupRuntimeFunc("goPanicSliceAlenU")
162		BoundsCheckFunc[ssa.BoundsSliceAcap] = typecheck.LookupRuntimeFunc("goPanicSliceAcap")
163		BoundsCheckFunc[ssa.BoundsSliceAcapU] = typecheck.LookupRuntimeFunc("goPanicSliceAcapU")
164		BoundsCheckFunc[ssa.BoundsSliceB] = typecheck.LookupRuntimeFunc("goPanicSliceB")
165		BoundsCheckFunc[ssa.BoundsSliceBU] = typecheck.LookupRuntimeFunc("goPanicSliceBU")
166		BoundsCheckFunc[ssa.BoundsSlice3Alen] = typecheck.LookupRuntimeFunc("goPanicSlice3Alen")
167		BoundsCheckFunc[ssa.BoundsSlice3AlenU] = typecheck.LookupRuntimeFunc("goPanicSlice3AlenU")
168		BoundsCheckFunc[ssa.BoundsSlice3Acap] = typecheck.LookupRuntimeFunc("goPanicSlice3Acap")
169		BoundsCheckFunc[ssa.BoundsSlice3AcapU] = typecheck.LookupRuntimeFunc("goPanicSlice3AcapU")
170		BoundsCheckFunc[ssa.BoundsSlice3B] = typecheck.LookupRuntimeFunc("goPanicSlice3B")
171		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("goPanicSlice3BU")
172		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("goPanicSlice3C")
173		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("goPanicSlice3CU")
174		BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("goPanicSliceConvert")
175	} else {
176		BoundsCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeFunc("panicIndex")
177		BoundsCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeFunc("panicIndexU")
178		BoundsCheckFunc[ssa.BoundsSliceAlen] = typecheck.LookupRuntimeFunc("panicSliceAlen")
179		BoundsCheckFunc[ssa.BoundsSliceAlenU] = typecheck.LookupRuntimeFunc("panicSliceAlenU")
180		BoundsCheckFunc[ssa.BoundsSliceAcap] = typecheck.LookupRuntimeFunc("panicSliceAcap")
181		BoundsCheckFunc[ssa.BoundsSliceAcapU] = typecheck.LookupRuntimeFunc("panicSliceAcapU")
182		BoundsCheckFunc[ssa.BoundsSliceB] = typecheck.LookupRuntimeFunc("panicSliceB")
183		BoundsCheckFunc[ssa.BoundsSliceBU] = typecheck.LookupRuntimeFunc("panicSliceBU")
184		BoundsCheckFunc[ssa.BoundsSlice3Alen] = typecheck.LookupRuntimeFunc("panicSlice3Alen")
185		BoundsCheckFunc[ssa.BoundsSlice3AlenU] = typecheck.LookupRuntimeFunc("panicSlice3AlenU")
186		BoundsCheckFunc[ssa.BoundsSlice3Acap] = typecheck.LookupRuntimeFunc("panicSlice3Acap")
187		BoundsCheckFunc[ssa.BoundsSlice3AcapU] = typecheck.LookupRuntimeFunc("panicSlice3AcapU")
188		BoundsCheckFunc[ssa.BoundsSlice3B] = typecheck.LookupRuntimeFunc("panicSlice3B")
189		BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("panicSlice3BU")
190		BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("panicSlice3C")
191		BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("panicSlice3CU")
192		BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("panicSliceConvert")
193	}
194	if Arch.LinkArch.PtrSize == 4 {
195		ExtendCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeVar("panicExtendIndex")
196		ExtendCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeVar("panicExtendIndexU")
197		ExtendCheckFunc[ssa.BoundsSliceAlen] = typecheck.LookupRuntimeVar("panicExtendSliceAlen")
198		ExtendCheckFunc[ssa.BoundsSliceAlenU] = typecheck.LookupRuntimeVar("panicExtendSliceAlenU")
199		ExtendCheckFunc[ssa.BoundsSliceAcap] = typecheck.LookupRuntimeVar("panicExtendSliceAcap")
200		ExtendCheckFunc[ssa.BoundsSliceAcapU] = typecheck.LookupRuntimeVar("panicExtendSliceAcapU")
201		ExtendCheckFunc[ssa.BoundsSliceB] = typecheck.LookupRuntimeVar("panicExtendSliceB")
202		ExtendCheckFunc[ssa.BoundsSliceBU] = typecheck.LookupRuntimeVar("panicExtendSliceBU")
203		ExtendCheckFunc[ssa.BoundsSlice3Alen] = typecheck.LookupRuntimeVar("panicExtendSlice3Alen")
204		ExtendCheckFunc[ssa.BoundsSlice3AlenU] = typecheck.LookupRuntimeVar("panicExtendSlice3AlenU")
205		ExtendCheckFunc[ssa.BoundsSlice3Acap] = typecheck.LookupRuntimeVar("panicExtendSlice3Acap")
206		ExtendCheckFunc[ssa.BoundsSlice3AcapU] = typecheck.LookupRuntimeVar("panicExtendSlice3AcapU")
207		ExtendCheckFunc[ssa.BoundsSlice3B] = typecheck.LookupRuntimeVar("panicExtendSlice3B")
208		ExtendCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeVar("panicExtendSlice3BU")
209		ExtendCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeVar("panicExtendSlice3C")
210		ExtendCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeVar("panicExtendSlice3CU")
211	}
212
213	// Wasm (all asm funcs with special ABIs)
214	ir.Syms.WasmDiv = typecheck.LookupRuntimeVar("wasmDiv")
215	ir.Syms.WasmTruncS = typecheck.LookupRuntimeVar("wasmTruncS")
216	ir.Syms.WasmTruncU = typecheck.LookupRuntimeVar("wasmTruncU")
217	ir.Syms.SigPanic = typecheck.LookupRuntimeFunc("sigpanic")
218}
219
220// AbiForBodylessFuncStackMap returns the ABI for a bodyless function's stack map.
221// This is not necessarily the ABI used to call it.
222// Currently (1.17 dev) such a stack map is always ABI0;
223// any ABI wrapper that is present is nosplit, hence a precise
224// stack map is not needed there (the parameters survive only long
225// enough to call the wrapped assembly function).
226// This always returns a freshly copied ABI.
227func AbiForBodylessFuncStackMap(fn *ir.Func) *abi.ABIConfig {
228	return ssaConfig.ABI0.Copy() // No idea what races will result, be safe
229}
230
231// abiForFunc implements ABI policy for a function, but does not return a copy of the ABI.
232// Passing a nil function returns the default ABI based on experiment configuration.
233func abiForFunc(fn *ir.Func, abi0, abi1 *abi.ABIConfig) *abi.ABIConfig {
234	if buildcfg.Experiment.RegabiArgs {
235		// Select the ABI based on the function's defining ABI.
236		if fn == nil {
237			return abi1
238		}
239		switch fn.ABI {
240		case obj.ABI0:
241			return abi0
242		case obj.ABIInternal:
243			// TODO(austin): Clean up the nomenclature here.
244			// It's not clear that "abi1" is ABIInternal.
245			return abi1
246		}
247		base.Fatalf("function %v has unknown ABI %v", fn, fn.ABI)
248		panic("not reachable")
249	}
250
251	a := abi0
252	if fn != nil {
253		if fn.Pragma&ir.RegisterParams != 0 { // TODO(register args) remove after register abi is working
254			a = abi1
255		}
256	}
257	return a
258}
259
260// emitOpenDeferInfo emits FUNCDATA information about the defers in a function
261// that is using open-coded defers.  This funcdata is used to determine the active
262// defers in a function and execute those defers during panic processing.
263//
264// The funcdata is all encoded in varints (since values will almost always be less than
265// 128, but stack offsets could potentially be up to 2Gbyte). All "locations" (offsets)
266// for stack variables are specified as the number of bytes below varp (pointer to the
267// top of the local variables) for their starting address. The format is:
268//
269//   - Offset of the deferBits variable
270//   - Offset of the first closure slot (the rest are laid out consecutively).
271func (s *state) emitOpenDeferInfo() {
272	firstOffset := s.openDefers[0].closureNode.FrameOffset()
273
274	// Verify that cmpstackvarlt laid out the slots in order.
275	for i, r := range s.openDefers {
276		have := r.closureNode.FrameOffset()
277		want := firstOffset + int64(i)*int64(types.PtrSize)
278		if have != want {
279			base.FatalfAt(s.curfn.Pos(), "unexpected frame offset for open-coded defer slot #%v: have %v, want %v", i, have, want)
280		}
281	}
282
283	x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer")
284	x.Set(obj.AttrContentAddressable, true)
285	s.curfn.LSym.Func().OpenCodedDeferInfo = x
286
287	off := 0
288	off = objw.Uvarint(x, off, uint64(-s.deferBitsTemp.FrameOffset()))
289	off = objw.Uvarint(x, off, uint64(-firstOffset))
290}
291
292// buildssa builds an SSA function for fn.
293// worker indicates which of the backend workers is doing the processing.
294func buildssa(fn *ir.Func, worker int, isPgoHot bool) *ssa.Func {
295	name := ir.FuncName(fn)
296
297	abiSelf := abiForFunc(fn, ssaConfig.ABI0, ssaConfig.ABI1)
298
299	printssa := false
300	// match either a simple name e.g. "(*Reader).Reset", package.name e.g. "compress/gzip.(*Reader).Reset", or subpackage name "gzip.(*Reader).Reset"
301	// optionally allows an ABI suffix specification in the GOSSAHASH, e.g. "(*Reader).Reset<0>" etc
302	if strings.Contains(ssaDump, name) { // in all the cases the function name is entirely contained within the GOSSAFUNC string.
303		nameOptABI := name
304		if strings.Contains(ssaDump, ",") { // ABI specification
305			nameOptABI = ssa.FuncNameABI(name, abiSelf.Which())
306		} else if strings.HasSuffix(ssaDump, ">") { // if they use the linker syntax instead....
307			l := len(ssaDump)
308			if l >= 3 && ssaDump[l-3] == '<' {
309				nameOptABI = ssa.FuncNameABI(name, abiSelf.Which())
310				ssaDump = ssaDump[:l-3] + "," + ssaDump[l-2:l-1]
311			}
312		}
313		pkgDotName := base.Ctxt.Pkgpath + "." + nameOptABI
314		printssa = nameOptABI == ssaDump || // "(*Reader).Reset"
315			pkgDotName == ssaDump || // "compress/gzip.(*Reader).Reset"
316			strings.HasSuffix(pkgDotName, ssaDump) && strings.HasSuffix(pkgDotName, "/"+ssaDump) // "gzip.(*Reader).Reset"
317	}
318
319	var astBuf *bytes.Buffer
320	if printssa {
321		astBuf = &bytes.Buffer{}
322		ir.FDumpList(astBuf, "buildssa-body", fn.Body)
323		if ssaDumpStdout {
324			fmt.Println("generating SSA for", name)
325			fmt.Print(astBuf.String())
326		}
327	}
328
329	var s state
330	s.pushLine(fn.Pos())
331	defer s.popLine()
332
333	s.hasdefer = fn.HasDefer()
334	if fn.Pragma&ir.CgoUnsafeArgs != 0 {
335		s.cgoUnsafeArgs = true
336	}
337	s.checkPtrEnabled = ir.ShouldCheckPtr(fn, 1)
338
339	if base.Flag.Cfg.Instrumenting && fn.Pragma&ir.Norace == 0 && !fn.Linksym().ABIWrapper() {
340		if !base.Flag.Race || !objabi.LookupPkgSpecial(fn.Sym().Pkg.Path).NoRaceFunc {
341			s.instrumentMemory = true
342		}
343		if base.Flag.Race {
344			s.instrumentEnterExit = true
345		}
346	}
347
348	fe := ssafn{
349		curfn: fn,
350		log:   printssa && ssaDumpStdout,
351	}
352	s.curfn = fn
353
354	cache := &ssaCaches[worker]
355	cache.Reset()
356
357	s.f = ssaConfig.NewFunc(&fe, cache)
358	s.config = ssaConfig
359	s.f.Type = fn.Type()
360	s.f.Name = name
361	s.f.PrintOrHtmlSSA = printssa
362	if fn.Pragma&ir.Nosplit != 0 {
363		s.f.NoSplit = true
364	}
365	s.f.ABI0 = ssaConfig.ABI0
366	s.f.ABI1 = ssaConfig.ABI1
367	s.f.ABIDefault = abiForFunc(nil, ssaConfig.ABI0, ssaConfig.ABI1)
368	s.f.ABISelf = abiSelf
369
370	s.panics = map[funcLine]*ssa.Block{}
371	s.softFloat = s.config.SoftFloat
372
373	// Allocate starting block
374	s.f.Entry = s.f.NewBlock(ssa.BlockPlain)
375	s.f.Entry.Pos = fn.Pos()
376	s.f.IsPgoHot = isPgoHot
377
378	if printssa {
379		ssaDF := ssaDumpFile
380		if ssaDir != "" {
381			ssaDF = filepath.Join(ssaDir, base.Ctxt.Pkgpath+"."+s.f.NameABI()+".html")
382			ssaD := filepath.Dir(ssaDF)
383			os.MkdirAll(ssaD, 0755)
384		}
385		s.f.HTMLWriter = ssa.NewHTMLWriter(ssaDF, s.f, ssaDumpCFG)
386		// TODO: generate and print a mapping from nodes to values and blocks
387		dumpSourcesColumn(s.f.HTMLWriter, fn)
388		s.f.HTMLWriter.WriteAST("AST", astBuf)
389	}
390
391	// Allocate starting values
392	s.labels = map[string]*ssaLabel{}
393	s.fwdVars = map[ir.Node]*ssa.Value{}
394	s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
395
396	s.hasOpenDefers = base.Flag.N == 0 && s.hasdefer && !s.curfn.OpenCodedDeferDisallowed()
397	switch {
398	case base.Debug.NoOpenDefer != 0:
399		s.hasOpenDefers = false
400	case s.hasOpenDefers && (base.Ctxt.Flag_shared || base.Ctxt.Flag_dynlink) && base.Ctxt.Arch.Name == "386":
401		// Don't support open-coded defers for 386 ONLY when using shared
402		// libraries, because there is extra code (added by rewriteToUseGot())
403		// preceding the deferreturn/ret code that we don't track correctly.
404		s.hasOpenDefers = false
405	}
406	if s.hasOpenDefers && s.instrumentEnterExit {
407		// Skip doing open defers if we need to instrument function
408		// returns for the race detector, since we will not generate that
409		// code in the case of the extra deferreturn/ret segment.
410		s.hasOpenDefers = false
411	}
412	if s.hasOpenDefers {
413		// Similarly, skip if there are any heap-allocated result
414		// parameters that need to be copied back to their stack slots.
415		for _, f := range s.curfn.Type().Results() {
416			if !f.Nname.(*ir.Name).OnStack() {
417				s.hasOpenDefers = false
418				break
419			}
420		}
421	}
422	if s.hasOpenDefers &&
423		s.curfn.NumReturns*s.curfn.NumDefers > 15 {
424		// Since we are generating defer calls at every exit for
425		// open-coded defers, skip doing open-coded defers if there are
426		// too many returns (especially if there are multiple defers).
427		// Open-coded defers are most important for improving performance
428		// for smaller functions (which don't have many returns).
429		s.hasOpenDefers = false
430	}
431
432	s.sp = s.entryNewValue0(ssa.OpSP, types.Types[types.TUINTPTR]) // TODO: use generic pointer type (unsafe.Pointer?) instead
433	s.sb = s.entryNewValue0(ssa.OpSB, types.Types[types.TUINTPTR])
434
435	s.startBlock(s.f.Entry)
436	s.vars[memVar] = s.startmem
437	if s.hasOpenDefers {
438		// Create the deferBits variable and stack slot.  deferBits is a
439		// bitmask showing which of the open-coded defers in this function
440		// have been activated.
441		deferBitsTemp := typecheck.TempAt(src.NoXPos, s.curfn, types.Types[types.TUINT8])
442		deferBitsTemp.SetAddrtaken(true)
443		s.deferBitsTemp = deferBitsTemp
444		// For this value, AuxInt is initialized to zero by default
445		startDeferBits := s.entryNewValue0(ssa.OpConst8, types.Types[types.TUINT8])
446		s.vars[deferBitsVar] = startDeferBits
447		s.deferBitsAddr = s.addr(deferBitsTemp)
448		s.store(types.Types[types.TUINT8], s.deferBitsAddr, startDeferBits)
449		// Make sure that the deferBits stack slot is kept alive (for use
450		// by panics) and stores to deferBits are not eliminated, even if
451		// all checking code on deferBits in the function exit can be
452		// eliminated, because the defer statements were all
453		// unconditional.
454		s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, deferBitsTemp, s.mem(), false)
455	}
456
457	var params *abi.ABIParamResultInfo
458	params = s.f.ABISelf.ABIAnalyze(fn.Type(), true)
459
460	// The backend's stackframe pass prunes away entries from the fn's
461	// Dcl list, including PARAMOUT nodes that correspond to output
462	// params passed in registers. Walk the Dcl list and capture these
463	// nodes to a side list, so that we'll have them available during
464	// DWARF-gen later on. See issue 48573 for more details.
465	var debugInfo ssa.FuncDebug
466	for _, n := range fn.Dcl {
467		if n.Class == ir.PPARAMOUT && n.IsOutputParamInRegisters() {
468			debugInfo.RegOutputParams = append(debugInfo.RegOutputParams, n)
469		}
470	}
471	fn.DebugInfo = &debugInfo
472
473	// Generate addresses of local declarations
474	s.decladdrs = map[*ir.Name]*ssa.Value{}
475	for _, n := range fn.Dcl {
476		switch n.Class {
477		case ir.PPARAM:
478			// Be aware that blank and unnamed input parameters will not appear here, but do appear in the type
479			s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type()), n, s.sp, s.startmem)
480		case ir.PPARAMOUT:
481			s.decladdrs[n] = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(n.Type()), n, s.sp, s.startmem)
482		case ir.PAUTO:
483			// processed at each use, to prevent Addr coming
484			// before the decl.
485		default:
486			s.Fatalf("local variable with class %v unimplemented", n.Class)
487		}
488	}
489
490	s.f.OwnAux = ssa.OwnAuxCall(fn.LSym, params)
491
492	// Populate SSAable arguments.
493	for _, n := range fn.Dcl {
494		if n.Class == ir.PPARAM {
495			if s.canSSA(n) {
496				v := s.newValue0A(ssa.OpArg, n.Type(), n)
497				s.vars[n] = v
498				s.addNamedValue(n, v) // This helps with debugging information, not needed for compilation itself.
499			} else { // address was taken AND/OR too large for SSA
500				paramAssignment := ssa.ParamAssignmentForArgName(s.f, n)
501				if len(paramAssignment.Registers) > 0 {
502					if ssa.CanSSA(n.Type()) { // SSA-able type, so address was taken -- receive value in OpArg, DO NOT bind to var, store immediately to memory.
503						v := s.newValue0A(ssa.OpArg, n.Type(), n)
504						s.store(n.Type(), s.decladdrs[n], v)
505					} else { // Too big for SSA.
506						// Brute force, and early, do a bunch of stores from registers
507						// Note that expand calls knows about this and doesn't trouble itself with larger-than-SSA-able Args in registers.
508						s.storeParameterRegsToStack(s.f.ABISelf, paramAssignment, n, s.decladdrs[n], false)
509					}
510				}
511			}
512		}
513	}
514
515	// Populate closure variables.
516	if fn.Needctxt() {
517		clo := s.entryNewValue0(ssa.OpGetClosurePtr, s.f.Config.Types.BytePtr)
518		if fn.RangeParent != nil {
519			// For a range body closure, keep its closure pointer live on the
520			// stack with a special name, so the debugger can look for it and
521			// find the parent frame.
522			sym := &types.Sym{Name: ".closureptr", Pkg: types.LocalPkg}
523			cloSlot := s.curfn.NewLocal(src.NoXPos, sym, s.f.Config.Types.BytePtr)
524			cloSlot.SetUsed(true)
525			cloSlot.SetEsc(ir.EscNever)
526			cloSlot.SetAddrtaken(true)
527			s.f.CloSlot = cloSlot
528			s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, cloSlot, s.mem(), false)
529			addr := s.addr(cloSlot)
530			s.store(s.f.Config.Types.BytePtr, addr, clo)
531			// Keep it from being dead-store eliminated.
532			s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, cloSlot, s.mem(), false)
533		}
534		csiter := typecheck.NewClosureStructIter(fn.ClosureVars)
535		for {
536			n, typ, offset := csiter.Next()
537			if n == nil {
538				break
539			}
540
541			ptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(typ), offset, clo)
542
543			// If n is a small variable captured by value, promote
544			// it to PAUTO so it can be converted to SSA.
545			//
546			// Note: While we never capture a variable by value if
547			// the user took its address, we may have generated
548			// runtime calls that did (#43701). Since we don't
549			// convert Addrtaken variables to SSA anyway, no point
550			// in promoting them either.
551			if n.Byval() && !n.Addrtaken() && ssa.CanSSA(n.Type()) {
552				n.Class = ir.PAUTO
553				fn.Dcl = append(fn.Dcl, n)
554				s.assign(n, s.load(n.Type(), ptr), false, 0)
555				continue
556			}
557
558			if !n.Byval() {
559				ptr = s.load(typ, ptr)
560			}
561			s.setHeapaddr(fn.Pos(), n, ptr)
562		}
563	}
564
565	// Convert the AST-based IR to the SSA-based IR
566	if s.instrumentEnterExit {
567		s.rtcall(ir.Syms.Racefuncenter, true, nil, s.newValue0(ssa.OpGetCallerPC, types.Types[types.TUINTPTR]))
568	}
569	s.zeroResults()
570	s.paramsToHeap()
571	s.stmtList(fn.Body)
572
573	// fallthrough to exit
574	if s.curBlock != nil {
575		s.pushLine(fn.Endlineno)
576		s.exit()
577		s.popLine()
578	}
579
580	for _, b := range s.f.Blocks {
581		if b.Pos != src.NoXPos {
582			s.updateUnsetPredPos(b)
583		}
584	}
585
586	s.f.HTMLWriter.WritePhase("before insert phis", "before insert phis")
587
588	s.insertPhis()
589
590	// Main call to ssa package to compile function
591	ssa.Compile(s.f)
592
593	fe.AllocFrame(s.f)
594
595	if len(s.openDefers) != 0 {
596		s.emitOpenDeferInfo()
597	}
598
599	// Record incoming parameter spill information for morestack calls emitted in the assembler.
600	// This is done here, using all the parameters (used, partially used, and unused) because
601	// it mimics the behavior of the former ABI (everything stored) and because it's not 100%
602	// clear if naming conventions are respected in autogenerated code.
603	// TODO figure out exactly what's unused, don't spill it. Make liveness fine-grained, also.
604	for _, p := range params.InParams() {
605		typs, offs := p.RegisterTypesAndOffsets()
606		for i, t := range typs {
607			o := offs[i]                // offset within parameter
608			fo := p.FrameOffset(params) // offset of parameter in frame
609			reg := ssa.ObjRegForAbiReg(p.Registers[i], s.f.Config)
610			s.f.RegArgs = append(s.f.RegArgs, ssa.Spill{Reg: reg, Offset: fo + o, Type: t})
611		}
612	}
613
614	return s.f
615}
616
617func (s *state) storeParameterRegsToStack(abi *abi.ABIConfig, paramAssignment *abi.ABIParamAssignment, n *ir.Name, addr *ssa.Value, pointersOnly bool) {
618	typs, offs := paramAssignment.RegisterTypesAndOffsets()
619	for i, t := range typs {
620		if pointersOnly && !t.IsPtrShaped() {
621			continue
622		}
623		r := paramAssignment.Registers[i]
624		o := offs[i]
625		op, reg := ssa.ArgOpAndRegisterFor(r, abi)
626		aux := &ssa.AuxNameOffset{Name: n, Offset: o}
627		v := s.newValue0I(op, t, reg)
628		v.Aux = aux
629		p := s.newValue1I(ssa.OpOffPtr, types.NewPtr(t), o, addr)
630		s.store(t, p, v)
631	}
632}
633
634// zeroResults zeros the return values at the start of the function.
635// We need to do this very early in the function.  Defer might stop a
636// panic and show the return values as they exist at the time of
637// panic.  For precise stacks, the garbage collector assumes results
638// are always live, so we need to zero them before any allocations,
639// even allocations to move params/results to the heap.
640func (s *state) zeroResults() {
641	for _, f := range s.curfn.Type().Results() {
642		n := f.Nname.(*ir.Name)
643		if !n.OnStack() {
644			// The local which points to the return value is the
645			// thing that needs zeroing. This is already handled
646			// by a Needzero annotation in plive.go:(*liveness).epilogue.
647			continue
648		}
649		// Zero the stack location containing f.
650		if typ := n.Type(); ssa.CanSSA(typ) {
651			s.assign(n, s.zeroVal(typ), false, 0)
652		} else {
653			if typ.HasPointers() || ssa.IsMergeCandidate(n) {
654				s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
655			}
656			s.zero(n.Type(), s.decladdrs[n])
657		}
658	}
659}
660
661// paramsToHeap produces code to allocate memory for heap-escaped parameters
662// and to copy non-result parameters' values from the stack.
663func (s *state) paramsToHeap() {
664	do := func(params []*types.Field) {
665		for _, f := range params {
666			if f.Nname == nil {
667				continue // anonymous or blank parameter
668			}
669			n := f.Nname.(*ir.Name)
670			if ir.IsBlank(n) || n.OnStack() {
671				continue
672			}
673			s.newHeapaddr(n)
674			if n.Class == ir.PPARAM {
675				s.move(n.Type(), s.expr(n.Heapaddr), s.decladdrs[n])
676			}
677		}
678	}
679
680	typ := s.curfn.Type()
681	do(typ.Recvs())
682	do(typ.Params())
683	do(typ.Results())
684}
685
686// newHeapaddr allocates heap memory for n and sets its heap address.
687func (s *state) newHeapaddr(n *ir.Name) {
688	s.setHeapaddr(n.Pos(), n, s.newObject(n.Type(), nil))
689}
690
691// setHeapaddr allocates a new PAUTO variable to store ptr (which must be non-nil)
692// and then sets it as n's heap address.
693func (s *state) setHeapaddr(pos src.XPos, n *ir.Name, ptr *ssa.Value) {
694	if !ptr.Type.IsPtr() || !types.Identical(n.Type(), ptr.Type.Elem()) {
695		base.FatalfAt(n.Pos(), "setHeapaddr %L with type %v", n, ptr.Type)
696	}
697
698	// Declare variable to hold address.
699	sym := &types.Sym{Name: "&" + n.Sym().Name, Pkg: types.LocalPkg}
700	addr := s.curfn.NewLocal(pos, sym, types.NewPtr(n.Type()))
701	addr.SetUsed(true)
702	types.CalcSize(addr.Type())
703
704	if n.Class == ir.PPARAMOUT {
705		addr.SetIsOutputParamHeapAddr(true)
706	}
707
708	n.Heapaddr = addr
709	s.assign(addr, ptr, false, 0)
710}
711
712// newObject returns an SSA value denoting new(typ).
713func (s *state) newObject(typ *types.Type, rtype *ssa.Value) *ssa.Value {
714	if typ.Size() == 0 {
715		return s.newValue1A(ssa.OpAddr, types.NewPtr(typ), ir.Syms.Zerobase, s.sb)
716	}
717	if rtype == nil {
718		rtype = s.reflectType(typ)
719	}
720	return s.rtcall(ir.Syms.Newobject, true, []*types.Type{types.NewPtr(typ)}, rtype)[0]
721}
722
723func (s *state) checkPtrAlignment(n *ir.ConvExpr, v *ssa.Value, count *ssa.Value) {
724	if !n.Type().IsPtr() {
725		s.Fatalf("expected pointer type: %v", n.Type())
726	}
727	elem, rtypeExpr := n.Type().Elem(), n.ElemRType
728	if count != nil {
729		if !elem.IsArray() {
730			s.Fatalf("expected array type: %v", elem)
731		}
732		elem, rtypeExpr = elem.Elem(), n.ElemElemRType
733	}
734	size := elem.Size()
735	// Casting from larger type to smaller one is ok, so for smallest type, do nothing.
736	if elem.Alignment() == 1 && (size == 0 || size == 1 || count == nil) {
737		return
738	}
739	if count == nil {
740		count = s.constInt(types.Types[types.TUINTPTR], 1)
741	}
742	if count.Type.Size() != s.config.PtrSize {
743		s.Fatalf("expected count fit to a uintptr size, have: %d, want: %d", count.Type.Size(), s.config.PtrSize)
744	}
745	var rtype *ssa.Value
746	if rtypeExpr != nil {
747		rtype = s.expr(rtypeExpr)
748	} else {
749		rtype = s.reflectType(elem)
750	}
751	s.rtcall(ir.Syms.CheckPtrAlignment, true, nil, v, rtype, count)
752}
753
754// reflectType returns an SSA value representing a pointer to typ's
755// reflection type descriptor.
756func (s *state) reflectType(typ *types.Type) *ssa.Value {
757	// TODO(mdempsky): Make this Fatalf under Unified IR; frontend needs
758	// to supply RType expressions.
759	lsym := reflectdata.TypeLinksym(typ)
760	return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(types.Types[types.TUINT8]), lsym, s.sb)
761}
762
763func dumpSourcesColumn(writer *ssa.HTMLWriter, fn *ir.Func) {
764	// Read sources of target function fn.
765	fname := base.Ctxt.PosTable.Pos(fn.Pos()).Filename()
766	targetFn, err := readFuncLines(fname, fn.Pos().Line(), fn.Endlineno.Line())
767	if err != nil {
768		writer.Logf("cannot read sources for function %v: %v", fn, err)
769	}
770
771	// Read sources of inlined functions.
772	var inlFns []*ssa.FuncLines
773	for _, fi := range ssaDumpInlined {
774		elno := fi.Endlineno
775		fname := base.Ctxt.PosTable.Pos(fi.Pos()).Filename()
776		fnLines, err := readFuncLines(fname, fi.Pos().Line(), elno.Line())
777		if err != nil {
778			writer.Logf("cannot read sources for inlined function %v: %v", fi, err)
779			continue
780		}
781		inlFns = append(inlFns, fnLines)
782	}
783
784	sort.Sort(ssa.ByTopo(inlFns))
785	if targetFn != nil {
786		inlFns = append([]*ssa.FuncLines{targetFn}, inlFns...)
787	}
788
789	writer.WriteSources("sources", inlFns)
790}
791
792func readFuncLines(file string, start, end uint) (*ssa.FuncLines, error) {
793	f, err := os.Open(os.ExpandEnv(file))
794	if err != nil {
795		return nil, err
796	}
797	defer f.Close()
798	var lines []string
799	ln := uint(1)
800	scanner := bufio.NewScanner(f)
801	for scanner.Scan() && ln <= end {
802		if ln >= start {
803			lines = append(lines, scanner.Text())
804		}
805		ln++
806	}
807	return &ssa.FuncLines{Filename: file, StartLineno: start, Lines: lines}, nil
808}
809
810// updateUnsetPredPos propagates the earliest-value position information for b
811// towards all of b's predecessors that need a position, and recurs on that
812// predecessor if its position is updated. B should have a non-empty position.
813func (s *state) updateUnsetPredPos(b *ssa.Block) {
814	if b.Pos == src.NoXPos {
815		s.Fatalf("Block %s should have a position", b)
816	}
817	bestPos := src.NoXPos
818	for _, e := range b.Preds {
819		p := e.Block()
820		if !p.LackingPos() {
821			continue
822		}
823		if bestPos == src.NoXPos {
824			bestPos = b.Pos
825			for _, v := range b.Values {
826				if v.LackingPos() {
827					continue
828				}
829				if v.Pos != src.NoXPos {
830					// Assume values are still in roughly textual order;
831					// TODO: could also seek minimum position?
832					bestPos = v.Pos
833					break
834				}
835			}
836		}
837		p.Pos = bestPos
838		s.updateUnsetPredPos(p) // We do not expect long chains of these, thus recursion is okay.
839	}
840}
841
842// Information about each open-coded defer.
843type openDeferInfo struct {
844	// The node representing the call of the defer
845	n *ir.CallExpr
846	// If defer call is closure call, the address of the argtmp where the
847	// closure is stored.
848	closure *ssa.Value
849	// The node representing the argtmp where the closure is stored - used for
850	// function, method, or interface call, to store a closure that panic
851	// processing can use for this defer.
852	closureNode *ir.Name
853}
854
855type state struct {
856	// configuration (arch) information
857	config *ssa.Config
858
859	// function we're building
860	f *ssa.Func
861
862	// Node for function
863	curfn *ir.Func
864
865	// labels in f
866	labels map[string]*ssaLabel
867
868	// unlabeled break and continue statement tracking
869	breakTo    *ssa.Block // current target for plain break statement
870	continueTo *ssa.Block // current target for plain continue statement
871
872	// current location where we're interpreting the AST
873	curBlock *ssa.Block
874
875	// variable assignments in the current block (map from variable symbol to ssa value)
876	// *Node is the unique identifier (an ONAME Node) for the variable.
877	// TODO: keep a single varnum map, then make all of these maps slices instead?
878	vars map[ir.Node]*ssa.Value
879
880	// fwdVars are variables that are used before they are defined in the current block.
881	// This map exists just to coalesce multiple references into a single FwdRef op.
882	// *Node is the unique identifier (an ONAME Node) for the variable.
883	fwdVars map[ir.Node]*ssa.Value
884
885	// all defined variables at the end of each block. Indexed by block ID.
886	defvars []map[ir.Node]*ssa.Value
887
888	// addresses of PPARAM and PPARAMOUT variables on the stack.
889	decladdrs map[*ir.Name]*ssa.Value
890
891	// starting values. Memory, stack pointer, and globals pointer
892	startmem *ssa.Value
893	sp       *ssa.Value
894	sb       *ssa.Value
895	// value representing address of where deferBits autotmp is stored
896	deferBitsAddr *ssa.Value
897	deferBitsTemp *ir.Name
898
899	// line number stack. The current line number is top of stack
900	line []src.XPos
901	// the last line number processed; it may have been popped
902	lastPos src.XPos
903
904	// list of panic calls by function name and line number.
905	// Used to deduplicate panic calls.
906	panics map[funcLine]*ssa.Block
907
908	cgoUnsafeArgs       bool
909	hasdefer            bool // whether the function contains a defer statement
910	softFloat           bool
911	hasOpenDefers       bool // whether we are doing open-coded defers
912	checkPtrEnabled     bool // whether to insert checkptr instrumentation
913	instrumentEnterExit bool // whether to instrument function enter/exit
914	instrumentMemory    bool // whether to instrument memory operations
915
916	// If doing open-coded defers, list of info about the defer calls in
917	// scanning order. Hence, at exit we should run these defers in reverse
918	// order of this list
919	openDefers []*openDeferInfo
920	// For open-coded defers, this is the beginning and end blocks of the last
921	// defer exit code that we have generated so far. We use these to share
922	// code between exits if the shareDeferExits option (disabled by default)
923	// is on.
924	lastDeferExit       *ssa.Block // Entry block of last defer exit code we generated
925	lastDeferFinalBlock *ssa.Block // Final block of last defer exit code we generated
926	lastDeferCount      int        // Number of defers encountered at that point
927
928	prevCall *ssa.Value // the previous call; use this to tie results to the call op.
929}
930
931type funcLine struct {
932	f    *obj.LSym
933	base *src.PosBase
934	line uint
935}
936
937type ssaLabel struct {
938	target         *ssa.Block // block identified by this label
939	breakTarget    *ssa.Block // block to break to in control flow node identified by this label
940	continueTarget *ssa.Block // block to continue to in control flow node identified by this label
941}
942
943// label returns the label associated with sym, creating it if necessary.
944func (s *state) label(sym *types.Sym) *ssaLabel {
945	lab := s.labels[sym.Name]
946	if lab == nil {
947		lab = new(ssaLabel)
948		s.labels[sym.Name] = lab
949	}
950	return lab
951}
952
953func (s *state) Logf(msg string, args ...interface{}) { s.f.Logf(msg, args...) }
954func (s *state) Log() bool                            { return s.f.Log() }
955func (s *state) Fatalf(msg string, args ...interface{}) {
956	s.f.Frontend().Fatalf(s.peekPos(), msg, args...)
957}
958func (s *state) Warnl(pos src.XPos, msg string, args ...interface{}) { s.f.Warnl(pos, msg, args...) }
959func (s *state) Debug_checknil() bool                                { return s.f.Frontend().Debug_checknil() }
960
961func ssaMarker(name string) *ir.Name {
962	return ir.NewNameAt(base.Pos, &types.Sym{Name: name}, nil)
963}
964
965var (
966	// marker node for the memory variable
967	memVar = ssaMarker("mem")
968
969	// marker nodes for temporary variables
970	ptrVar       = ssaMarker("ptr")
971	lenVar       = ssaMarker("len")
972	capVar       = ssaMarker("cap")
973	typVar       = ssaMarker("typ")
974	okVar        = ssaMarker("ok")
975	deferBitsVar = ssaMarker("deferBits")
976	hashVar      = ssaMarker("hash")
977)
978
979// startBlock sets the current block we're generating code in to b.
980func (s *state) startBlock(b *ssa.Block) {
981	if s.curBlock != nil {
982		s.Fatalf("starting block %v when block %v has not ended", b, s.curBlock)
983	}
984	s.curBlock = b
985	s.vars = map[ir.Node]*ssa.Value{}
986	for n := range s.fwdVars {
987		delete(s.fwdVars, n)
988	}
989}
990
991// endBlock marks the end of generating code for the current block.
992// Returns the (former) current block. Returns nil if there is no current
993// block, i.e. if no code flows to the current execution point.
994func (s *state) endBlock() *ssa.Block {
995	b := s.curBlock
996	if b == nil {
997		return nil
998	}
999	for len(s.defvars) <= int(b.ID) {
1000		s.defvars = append(s.defvars, nil)
1001	}
1002	s.defvars[b.ID] = s.vars
1003	s.curBlock = nil
1004	s.vars = nil
1005	if b.LackingPos() {
1006		// Empty plain blocks get the line of their successor (handled after all blocks created),
1007		// except for increment blocks in For statements (handled in ssa conversion of OFOR),
1008		// and for blocks ending in GOTO/BREAK/CONTINUE.
1009		b.Pos = src.NoXPos
1010	} else {
1011		b.Pos = s.lastPos
1012	}
1013	return b
1014}
1015
1016// pushLine pushes a line number on the line number stack.
1017func (s *state) pushLine(line src.XPos) {
1018	if !line.IsKnown() {
1019		// the frontend may emit node with line number missing,
1020		// use the parent line number in this case.
1021		line = s.peekPos()
1022		if base.Flag.K != 0 {
1023			base.Warn("buildssa: unknown position (line 0)")
1024		}
1025	} else {
1026		s.lastPos = line
1027	}
1028
1029	s.line = append(s.line, line)
1030}
1031
1032// popLine pops the top of the line number stack.
1033func (s *state) popLine() {
1034	s.line = s.line[:len(s.line)-1]
1035}
1036
1037// peekPos peeks the top of the line number stack.
1038func (s *state) peekPos() src.XPos {
1039	return s.line[len(s.line)-1]
1040}
1041
1042// newValue0 adds a new value with no arguments to the current block.
1043func (s *state) newValue0(op ssa.Op, t *types.Type) *ssa.Value {
1044	return s.curBlock.NewValue0(s.peekPos(), op, t)
1045}
1046
1047// newValue0A adds a new value with no arguments and an aux value to the current block.
1048func (s *state) newValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
1049	return s.curBlock.NewValue0A(s.peekPos(), op, t, aux)
1050}
1051
1052// newValue0I adds a new value with no arguments and an auxint value to the current block.
1053func (s *state) newValue0I(op ssa.Op, t *types.Type, auxint int64) *ssa.Value {
1054	return s.curBlock.NewValue0I(s.peekPos(), op, t, auxint)
1055}
1056
1057// newValue1 adds a new value with one argument to the current block.
1058func (s *state) newValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
1059	return s.curBlock.NewValue1(s.peekPos(), op, t, arg)
1060}
1061
1062// newValue1A adds a new value with one argument and an aux value to the current block.
1063func (s *state) newValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
1064	return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
1065}
1066
1067// newValue1Apos adds a new value with one argument and an aux value to the current block.
1068// isStmt determines whether the created values may be a statement or not
1069// (i.e., false means never, yes means maybe).
1070func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value, isStmt bool) *ssa.Value {
1071	if isStmt {
1072		return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
1073	}
1074	return s.curBlock.NewValue1A(s.peekPos().WithNotStmt(), op, t, aux, arg)
1075}
1076
1077// newValue1I adds a new value with one argument and an auxint value to the current block.
1078func (s *state) newValue1I(op ssa.Op, t *types.Type, aux int64, arg *ssa.Value) *ssa.Value {
1079	return s.curBlock.NewValue1I(s.peekPos(), op, t, aux, arg)
1080}
1081
1082// newValue2 adds a new value with two arguments to the current block.
1083func (s *state) newValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.Value {
1084	return s.curBlock.NewValue2(s.peekPos(), op, t, arg0, arg1)
1085}
1086
1087// newValue2A adds a new value with two arguments and an aux value to the current block.
1088func (s *state) newValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
1089	return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
1090}
1091
1092// newValue2Apos adds a new value with two arguments and an aux value to the current block.
1093// isStmt determines whether the created values may be a statement or not
1094// (i.e., false means never, yes means maybe).
1095func (s *state) newValue2Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value, isStmt bool) *ssa.Value {
1096	if isStmt {
1097		return s.curBlock.NewValue2A(s.peekPos(), op, t, aux, arg0, arg1)
1098	}
1099	return s.curBlock.NewValue2A(s.peekPos().WithNotStmt(), op, t, aux, arg0, arg1)
1100}
1101
1102// newValue2I adds a new value with two arguments and an auxint value to the current block.
1103func (s *state) newValue2I(op ssa.Op, t *types.Type, aux int64, arg0, arg1 *ssa.Value) *ssa.Value {
1104	return s.curBlock.NewValue2I(s.peekPos(), op, t, aux, arg0, arg1)
1105}
1106
1107// newValue3 adds a new value with three arguments to the current block.
1108func (s *state) newValue3(op ssa.Op, t *types.Type, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
1109	return s.curBlock.NewValue3(s.peekPos(), op, t, arg0, arg1, arg2)
1110}
1111
1112// newValue3I adds a new value with three arguments and an auxint value to the current block.
1113func (s *state) newValue3I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
1114	return s.curBlock.NewValue3I(s.peekPos(), op, t, aux, arg0, arg1, arg2)
1115}
1116
1117// newValue3A adds a new value with three arguments and an aux value to the current block.
1118func (s *state) newValue3A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value) *ssa.Value {
1119	return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
1120}
1121
1122// newValue3Apos adds a new value with three arguments and an aux value to the current block.
1123// isStmt determines whether the created values may be a statement or not
1124// (i.e., false means never, yes means maybe).
1125func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
1126	if isStmt {
1127		return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
1128	}
1129	return s.curBlock.NewValue3A(s.peekPos().WithNotStmt(), op, t, aux, arg0, arg1, arg2)
1130}
1131
1132// newValue4 adds a new value with four arguments to the current block.
1133func (s *state) newValue4(op ssa.Op, t *types.Type, arg0, arg1, arg2, arg3 *ssa.Value) *ssa.Value {
1134	return s.curBlock.NewValue4(s.peekPos(), op, t, arg0, arg1, arg2, arg3)
1135}
1136
1137// newValue4I adds a new value with four arguments and an auxint value to the current block.
1138func (s *state) newValue4I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2, arg3 *ssa.Value) *ssa.Value {
1139	return s.curBlock.NewValue4I(s.peekPos(), op, t, aux, arg0, arg1, arg2, arg3)
1140}
1141
1142func (s *state) entryBlock() *ssa.Block {
1143	b := s.f.Entry
1144	if base.Flag.N > 0 && s.curBlock != nil {
1145		// If optimizations are off, allocate in current block instead. Since with -N
1146		// we're not doing the CSE or tighten passes, putting lots of stuff in the
1147		// entry block leads to O(n^2) entries in the live value map during regalloc.
1148		// See issue 45897.
1149		b = s.curBlock
1150	}
1151	return b
1152}
1153
1154// entryNewValue0 adds a new value with no arguments to the entry block.
1155func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value {
1156	return s.entryBlock().NewValue0(src.NoXPos, op, t)
1157}
1158
1159// entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
1160func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
1161	return s.entryBlock().NewValue0A(src.NoXPos, op, t, aux)
1162}
1163
1164// entryNewValue1 adds a new value with one argument to the entry block.
1165func (s *state) entryNewValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
1166	return s.entryBlock().NewValue1(src.NoXPos, op, t, arg)
1167}
1168
1169// entryNewValue1I adds a new value with one argument and an auxint value to the entry block.
1170func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa.Value) *ssa.Value {
1171	return s.entryBlock().NewValue1I(src.NoXPos, op, t, auxint, arg)
1172}
1173
1174// entryNewValue1A adds a new value with one argument and an aux value to the entry block.
1175func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
1176	return s.entryBlock().NewValue1A(src.NoXPos, op, t, aux, arg)
1177}
1178
1179// entryNewValue2 adds a new value with two arguments to the entry block.
1180func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.Value {
1181	return s.entryBlock().NewValue2(src.NoXPos, op, t, arg0, arg1)
1182}
1183
1184// entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
1185func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
1186	return s.entryBlock().NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
1187}
1188
1189// const* routines add a new const value to the entry block.
1190func (s *state) constSlice(t *types.Type) *ssa.Value {
1191	return s.f.ConstSlice(t)
1192}
1193func (s *state) constInterface(t *types.Type) *ssa.Value {
1194	return s.f.ConstInterface(t)
1195}
1196func (s *state) constNil(t *types.Type) *ssa.Value { return s.f.ConstNil(t) }
1197func (s *state) constEmptyString(t *types.Type) *ssa.Value {
1198	return s.f.ConstEmptyString(t)
1199}
1200func (s *state) constBool(c bool) *ssa.Value {
1201	return s.f.ConstBool(types.Types[types.TBOOL], c)
1202}
1203func (s *state) constInt8(t *types.Type, c int8) *ssa.Value {
1204	return s.f.ConstInt8(t, c)
1205}
1206func (s *state) constInt16(t *types.Type, c int16) *ssa.Value {
1207	return s.f.ConstInt16(t, c)
1208}
1209func (s *state) constInt32(t *types.Type, c int32) *ssa.Value {
1210	return s.f.ConstInt32(t, c)
1211}
1212func (s *state) constInt64(t *types.Type, c int64) *ssa.Value {
1213	return s.f.ConstInt64(t, c)
1214}
1215func (s *state) constFloat32(t *types.Type, c float64) *ssa.Value {
1216	return s.f.ConstFloat32(t, c)
1217}
1218func (s *state) constFloat64(t *types.Type, c float64) *ssa.Value {
1219	return s.f.ConstFloat64(t, c)
1220}
1221func (s *state) constInt(t *types.Type, c int64) *ssa.Value {
1222	if s.config.PtrSize == 8 {
1223		return s.constInt64(t, c)
1224	}
1225	if int64(int32(c)) != c {
1226		s.Fatalf("integer constant too big %d", c)
1227	}
1228	return s.constInt32(t, int32(c))
1229}
1230func (s *state) constOffPtrSP(t *types.Type, c int64) *ssa.Value {
1231	return s.f.ConstOffPtrSP(t, c, s.sp)
1232}
1233
1234// newValueOrSfCall* are wrappers around newValue*, which may create a call to a
1235// soft-float runtime function instead (when emitting soft-float code).
1236func (s *state) newValueOrSfCall1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
1237	if s.softFloat {
1238		if c, ok := s.sfcall(op, arg); ok {
1239			return c
1240		}
1241	}
1242	return s.newValue1(op, t, arg)
1243}
1244func (s *state) newValueOrSfCall2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.Value {
1245	if s.softFloat {
1246		if c, ok := s.sfcall(op, arg0, arg1); ok {
1247			return c
1248		}
1249	}
1250	return s.newValue2(op, t, arg0, arg1)
1251}
1252
1253type instrumentKind uint8
1254
1255const (
1256	instrumentRead = iota
1257	instrumentWrite
1258	instrumentMove
1259)
1260
1261func (s *state) instrument(t *types.Type, addr *ssa.Value, kind instrumentKind) {
1262	s.instrument2(t, addr, nil, kind)
1263}
1264
1265// instrumentFields instruments a read/write operation on addr.
1266// If it is instrumenting for MSAN or ASAN and t is a struct type, it instruments
1267// operation for each field, instead of for the whole struct.
1268func (s *state) instrumentFields(t *types.Type, addr *ssa.Value, kind instrumentKind) {
1269	if !(base.Flag.MSan || base.Flag.ASan) || !t.IsStruct() {
1270		s.instrument(t, addr, kind)
1271		return
1272	}
1273	for _, f := range t.Fields() {
1274		if f.Sym.IsBlank() {
1275			continue
1276		}
1277		offptr := s.newValue1I(ssa.OpOffPtr, types.NewPtr(f.Type), f.Offset, addr)
1278		s.instrumentFields(f.Type, offptr, kind)
1279	}
1280}
1281
1282func (s *state) instrumentMove(t *types.Type, dst, src *ssa.Value) {
1283	if base.Flag.MSan {
1284		s.instrument2(t, dst, src, instrumentMove)
1285	} else {
1286		s.instrument(t, src, instrumentRead)
1287		s.instrument(t, dst, instrumentWrite)
1288	}
1289}
1290
1291func (s *state) instrument2(t *types.Type, addr, addr2 *ssa.Value, kind instrumentKind) {
1292	if !s.instrumentMemory {
1293		return
1294	}
1295
1296	w := t.Size()
1297	if w == 0 {
1298		return // can't race on zero-sized things
1299	}
1300
1301	if ssa.IsSanitizerSafeAddr(addr) {
1302		return
1303	}
1304
1305	var fn *obj.LSym
1306	needWidth := false
1307
1308	if addr2 != nil && kind != instrumentMove {
1309		panic("instrument2: non-nil addr2 for non-move instrumentation")
1310	}
1311
1312	if base.Flag.MSan {
1313		switch kind {
1314		case instrumentRead:
1315			fn = ir.Syms.Msanread
1316		case instrumentWrite:
1317			fn = ir.Syms.Msanwrite
1318		case instrumentMove:
1319			fn = ir.Syms.Msanmove
1320		default:
1321			panic("unreachable")
1322		}
1323		needWidth = true
1324	} else if base.Flag.Race && t.NumComponents(types.CountBlankFields) > 1 {
1325		// for composite objects we have to write every address
1326		// because a write might happen to any subobject.
1327		// composites with only one element don't have subobjects, though.
1328		switch kind {
1329		case instrumentRead:
1330			fn = ir.Syms.Racereadrange
1331		case instrumentWrite:
1332			fn = ir.Syms.Racewriterange
1333		default:
1334			panic("unreachable")
1335		}
1336		needWidth = true
1337	} else if base.Flag.Race {
1338		// for non-composite objects we can write just the start
1339		// address, as any write must write the first byte.
1340		switch kind {
1341		case instrumentRead:
1342			fn = ir.Syms.Raceread
1343		case instrumentWrite:
1344			fn = ir.Syms.Racewrite
1345		default:
1346			panic("unreachable")
1347		}
1348	} else if base.Flag.ASan {
1349		switch kind {
1350		case instrumentRead:
1351			fn = ir.Syms.Asanread
1352		case instrumentWrite:
1353			fn = ir.Syms.Asanwrite
1354		default:
1355			panic("unreachable")
1356		}
1357		needWidth = true
1358	} else {
1359		panic("unreachable")
1360	}
1361
1362	args := []*ssa.Value{addr}
1363	if addr2 != nil {
1364		args = append(args, addr2)
1365	}
1366	if needWidth {
1367		args = append(args, s.constInt(types.Types[types.TUINTPTR], w))
1368	}
1369	s.rtcall(fn, true, nil, args...)
1370}
1371
1372func (s *state) load(t *types.Type, src *ssa.Value) *ssa.Value {
1373	s.instrumentFields(t, src, instrumentRead)
1374	return s.rawLoad(t, src)
1375}
1376
1377func (s *state) rawLoad(t *types.Type, src *ssa.Value) *ssa.Value {
1378	return s.newValue2(ssa.OpLoad, t, src, s.mem())
1379}
1380
1381func (s *state) store(t *types.Type, dst, val *ssa.Value) {
1382	s.vars[memVar] = s.newValue3A(ssa.OpStore, types.TypeMem, t, dst, val, s.mem())
1383}
1384
1385func (s *state) zero(t *types.Type, dst *ssa.Value) {
1386	s.instrument(t, dst, instrumentWrite)
1387	store := s.newValue2I(ssa.OpZero, types.TypeMem, t.Size(), dst, s.mem())
1388	store.Aux = t
1389	s.vars[memVar] = store
1390}
1391
1392func (s *state) move(t *types.Type, dst, src *ssa.Value) {
1393	s.moveWhichMayOverlap(t, dst, src, false)
1394}
1395func (s *state) moveWhichMayOverlap(t *types.Type, dst, src *ssa.Value, mayOverlap bool) {
1396	s.instrumentMove(t, dst, src)
1397	if mayOverlap && t.IsArray() && t.NumElem() > 1 && !ssa.IsInlinableMemmove(dst, src, t.Size(), s.f.Config) {
1398		// Normally, when moving Go values of type T from one location to another,
1399		// we don't need to worry about partial overlaps. The two Ts must either be
1400		// in disjoint (nonoverlapping) memory or in exactly the same location.
1401		// There are 2 cases where this isn't true:
1402		//  1) Using unsafe you can arrange partial overlaps.
1403		//  2) Since Go 1.17, you can use a cast from a slice to a ptr-to-array.
1404		//     https://go.dev/ref/spec#Conversions_from_slice_to_array_pointer
1405		//     This feature can be used to construct partial overlaps of array types.
1406		//       var a [3]int
1407		//       p := (*[2]int)(a[:])
1408		//       q := (*[2]int)(a[1:])
1409		//       *p = *q
1410		// We don't care about solving 1. Or at least, we haven't historically
1411		// and no one has complained.
1412		// For 2, we need to ensure that if there might be partial overlap,
1413		// then we can't use OpMove; we must use memmove instead.
1414		// (memmove handles partial overlap by copying in the correct
1415		// direction. OpMove does not.)
1416		//
1417		// Note that we have to be careful here not to introduce a call when
1418		// we're marshaling arguments to a call or unmarshaling results from a call.
1419		// Cases where this is happening must pass mayOverlap to false.
1420		// (Currently this only happens when unmarshaling results of a call.)
1421		if t.HasPointers() {
1422			s.rtcall(ir.Syms.Typedmemmove, true, nil, s.reflectType(t), dst, src)
1423			// We would have otherwise implemented this move with straightline code,
1424			// including a write barrier. Pretend we issue a write barrier here,
1425			// so that the write barrier tests work. (Otherwise they'd need to know
1426			// the details of IsInlineableMemmove.)
1427			s.curfn.SetWBPos(s.peekPos())
1428		} else {
1429			s.rtcall(ir.Syms.Memmove, true, nil, dst, src, s.constInt(types.Types[types.TUINTPTR], t.Size()))
1430		}
1431		ssa.LogLargeCopy(s.f.Name, s.peekPos(), t.Size())
1432		return
1433	}
1434	store := s.newValue3I(ssa.OpMove, types.TypeMem, t.Size(), dst, src, s.mem())
1435	store.Aux = t
1436	s.vars[memVar] = store
1437}
1438
1439// stmtList converts the statement list n to SSA and adds it to s.
1440func (s *state) stmtList(l ir.Nodes) {
1441	for _, n := range l {
1442		s.stmt(n)
1443	}
1444}
1445
1446// stmt converts the statement n to SSA and adds it to s.
1447func (s *state) stmt(n ir.Node) {
1448	s.pushLine(n.Pos())
1449	defer s.popLine()
1450
1451	// If s.curBlock is nil, and n isn't a label (which might have an associated goto somewhere),
1452	// then this code is dead. Stop here.
1453	if s.curBlock == nil && n.Op() != ir.OLABEL {
1454		return
1455	}
1456
1457	s.stmtList(n.Init())
1458	switch n.Op() {
1459
1460	case ir.OBLOCK:
1461		n := n.(*ir.BlockStmt)
1462		s.stmtList(n.List)
1463
1464	case ir.OFALL: // no-op
1465
1466	// Expression statements
1467	case ir.OCALLFUNC:
1468		n := n.(*ir.CallExpr)
1469		if ir.IsIntrinsicCall(n) {
1470			s.intrinsicCall(n)
1471			return
1472		}
1473		fallthrough
1474
1475	case ir.OCALLINTER:
1476		n := n.(*ir.CallExpr)
1477		s.callResult(n, callNormal)
1478		if n.Op() == ir.OCALLFUNC && n.Fun.Op() == ir.ONAME && n.Fun.(*ir.Name).Class == ir.PFUNC {
1479			if fn := n.Fun.Sym().Name; base.Flag.CompilingRuntime && fn == "throw" ||
1480				n.Fun.Sym().Pkg == ir.Pkgs.Runtime &&
1481					(fn == "throwinit" || fn == "gopanic" || fn == "panicwrap" || fn == "block" ||
1482						fn == "panicmakeslicelen" || fn == "panicmakeslicecap" || fn == "panicunsafeslicelen" ||
1483						fn == "panicunsafeslicenilptr" || fn == "panicunsafestringlen" || fn == "panicunsafestringnilptr" ||
1484						fn == "panicrangestate") {
1485				m := s.mem()
1486				b := s.endBlock()
1487				b.Kind = ssa.BlockExit
1488				b.SetControl(m)
1489				// TODO: never rewrite OPANIC to OCALLFUNC in the
1490				// first place. Need to wait until all backends
1491				// go through SSA.
1492			}
1493		}
1494	case ir.ODEFER:
1495		n := n.(*ir.GoDeferStmt)
1496		if base.Debug.Defer > 0 {
1497			var defertype string
1498			if s.hasOpenDefers {
1499				defertype = "open-coded"
1500			} else if n.Esc() == ir.EscNever {
1501				defertype = "stack-allocated"
1502			} else {
1503				defertype = "heap-allocated"
1504			}
1505			base.WarnfAt(n.Pos(), "%s defer", defertype)
1506		}
1507		if s.hasOpenDefers {
1508			s.openDeferRecord(n.Call.(*ir.CallExpr))
1509		} else {
1510			d := callDefer
1511			if n.Esc() == ir.EscNever && n.DeferAt == nil {
1512				d = callDeferStack
1513			}
1514			s.call(n.Call.(*ir.CallExpr), d, false, n.DeferAt)
1515		}
1516	case ir.OGO:
1517		n := n.(*ir.GoDeferStmt)
1518		s.callResult(n.Call.(*ir.CallExpr), callGo)
1519
1520	case ir.OAS2DOTTYPE:
1521		n := n.(*ir.AssignListStmt)
1522		var res, resok *ssa.Value
1523		if n.Rhs[0].Op() == ir.ODOTTYPE2 {
1524			res, resok = s.dottype(n.Rhs[0].(*ir.TypeAssertExpr), true)
1525		} else {
1526			res, resok = s.dynamicDottype(n.Rhs[0].(*ir.DynamicTypeAssertExpr), true)
1527		}
1528		deref := false
1529		if !ssa.CanSSA(n.Rhs[0].Type()) {
1530			if res.Op != ssa.OpLoad {
1531				s.Fatalf("dottype of non-load")
1532			}
1533			mem := s.mem()
1534			if res.Args[1] != mem {
1535				s.Fatalf("memory no longer live from 2-result dottype load")
1536			}
1537			deref = true
1538			res = res.Args[0]
1539		}
1540		s.assign(n.Lhs[0], res, deref, 0)
1541		s.assign(n.Lhs[1], resok, false, 0)
1542		return
1543
1544	case ir.OAS2FUNC:
1545		// We come here only when it is an intrinsic call returning two values.
1546		n := n.(*ir.AssignListStmt)
1547		call := n.Rhs[0].(*ir.CallExpr)
1548		if !ir.IsIntrinsicCall(call) {
1549			s.Fatalf("non-intrinsic AS2FUNC not expanded %v", call)
1550		}
1551		v := s.intrinsicCall(call)
1552		v1 := s.newValue1(ssa.OpSelect0, n.Lhs[0].Type(), v)
1553		v2 := s.newValue1(ssa.OpSelect1, n.Lhs[1].Type(), v)
1554		s.assign(n.Lhs[0], v1, false, 0)
1555		s.assign(n.Lhs[1], v2, false, 0)
1556		return
1557
1558	case ir.ODCL:
1559		n := n.(*ir.Decl)
1560		if v := n.X; v.Esc() == ir.EscHeap {
1561			s.newHeapaddr(v)
1562		}
1563
1564	case ir.OLABEL:
1565		n := n.(*ir.LabelStmt)
1566		sym := n.Label
1567		if sym.IsBlank() {
1568			// Nothing to do because the label isn't targetable. See issue 52278.
1569			break
1570		}
1571		lab := s.label(sym)
1572
1573		// The label might already have a target block via a goto.
1574		if lab.target == nil {
1575			lab.target = s.f.NewBlock(ssa.BlockPlain)
1576		}
1577
1578		// Go to that label.
1579		// (We pretend "label:" is preceded by "goto label", unless the predecessor is unreachable.)
1580		if s.curBlock != nil {
1581			b := s.endBlock()
1582			b.AddEdgeTo(lab.target)
1583		}
1584		s.startBlock(lab.target)
1585
1586	case ir.OGOTO:
1587		n := n.(*ir.BranchStmt)
1588		sym := n.Label
1589
1590		lab := s.label(sym)
1591		if lab.target == nil {
1592			lab.target = s.f.NewBlock(ssa.BlockPlain)
1593		}
1594
1595		b := s.endBlock()
1596		b.Pos = s.lastPos.WithIsStmt() // Do this even if b is an empty block.
1597		b.AddEdgeTo(lab.target)
1598
1599	case ir.OAS:
1600		n := n.(*ir.AssignStmt)
1601		if n.X == n.Y && n.X.Op() == ir.ONAME {
1602			// An x=x assignment. No point in doing anything
1603			// here. In addition, skipping this assignment
1604			// prevents generating:
1605			//   VARDEF x
1606			//   COPY x -> x
1607			// which is bad because x is incorrectly considered
1608			// dead before the vardef. See issue #14904.
1609			return
1610		}
1611
1612		// mayOverlap keeps track of whether the LHS and RHS might
1613		// refer to partially overlapping memory. Partial overlapping can
1614		// only happen for arrays, see the comment in moveWhichMayOverlap.
1615		//
1616		// If both sides of the assignment are not dereferences, then partial
1617		// overlap can't happen. Partial overlap can only occur only when the
1618		// arrays referenced are strictly smaller parts of the same base array.
1619		// If one side of the assignment is a full array, then partial overlap
1620		// can't happen. (The arrays are either disjoint or identical.)
1621		mayOverlap := n.X.Op() == ir.ODEREF && (n.Y != nil && n.Y.Op() == ir.ODEREF)
1622		if n.Y != nil && n.Y.Op() == ir.ODEREF {
1623			p := n.Y.(*ir.StarExpr).X
1624			for p.Op() == ir.OCONVNOP {
1625				p = p.(*ir.ConvExpr).X
1626			}
1627			if p.Op() == ir.OSPTR && p.(*ir.UnaryExpr).X.Type().IsString() {
1628				// Pointer fields of strings point to unmodifiable memory.
1629				// That memory can't overlap with the memory being written.
1630				mayOverlap = false
1631			}
1632		}
1633
1634		// Evaluate RHS.
1635		rhs := n.Y
1636		if rhs != nil {
1637			switch rhs.Op() {
1638			case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT:
1639				// All literals with nonzero fields have already been
1640				// rewritten during walk. Any that remain are just T{}
1641				// or equivalents. Use the zero value.
1642				if !ir.IsZero(rhs) {
1643					s.Fatalf("literal with nonzero value in SSA: %v", rhs)
1644				}
1645				rhs = nil
1646			case ir.OAPPEND:
1647				rhs := rhs.(*ir.CallExpr)
1648				// Check whether we're writing the result of an append back to the same slice.
1649				// If so, we handle it specially to avoid write barriers on the fast
1650				// (non-growth) path.
1651				if !ir.SameSafeExpr(n.X, rhs.Args[0]) || base.Flag.N != 0 {
1652					break
1653				}
1654				// If the slice can be SSA'd, it'll be on the stack,
1655				// so there will be no write barriers,
1656				// so there's no need to attempt to prevent them.
1657				if s.canSSA(n.X) {
1658					if base.Debug.Append > 0 { // replicating old diagnostic message
1659						base.WarnfAt(n.Pos(), "append: len-only update (in local slice)")
1660					}
1661					break
1662				}
1663				if base.Debug.Append > 0 {
1664					base.WarnfAt(n.Pos(), "append: len-only update")
1665				}
1666				s.append(rhs, true)
1667				return
1668			}
1669		}
1670
1671		if ir.IsBlank(n.X) {
1672			// _ = rhs
1673			// Just evaluate rhs for side-effects.
1674			if rhs != nil {
1675				s.expr(rhs)
1676			}
1677			return
1678		}
1679
1680		var t *types.Type
1681		if n.Y != nil {
1682			t = n.Y.Type()
1683		} else {
1684			t = n.X.Type()
1685		}
1686
1687		var r *ssa.Value
1688		deref := !ssa.CanSSA(t)
1689		if deref {
1690			if rhs == nil {
1691				r = nil // Signal assign to use OpZero.
1692			} else {
1693				r = s.addr(rhs)
1694			}
1695		} else {
1696			if rhs == nil {
1697				r = s.zeroVal(t)
1698			} else {
1699				r = s.expr(rhs)
1700			}
1701		}
1702
1703		var skip skipMask
1704		if rhs != nil && (rhs.Op() == ir.OSLICE || rhs.Op() == ir.OSLICE3 || rhs.Op() == ir.OSLICESTR) && ir.SameSafeExpr(rhs.(*ir.SliceExpr).X, n.X) {
1705			// We're assigning a slicing operation back to its source.
1706			// Don't write back fields we aren't changing. See issue #14855.
1707			rhs := rhs.(*ir.SliceExpr)
1708			i, j, k := rhs.Low, rhs.High, rhs.Max
1709			if i != nil && (i.Op() == ir.OLITERAL && i.Val().Kind() == constant.Int && ir.Int64Val(i) == 0) {
1710				// [0:...] is the same as [:...]
1711				i = nil
1712			}
1713			// TODO: detect defaults for len/cap also.
1714			// Currently doesn't really work because (*p)[:len(*p)] appears here as:
1715			//    tmp = len(*p)
1716			//    (*p)[:tmp]
1717			// if j != nil && (j.Op == OLEN && SameSafeExpr(j.Left, n.Left)) {
1718			//      j = nil
1719			// }
1720			// if k != nil && (k.Op == OCAP && SameSafeExpr(k.Left, n.Left)) {
1721			//      k = nil
1722			// }
1723			if i == nil {
1724				skip |= skipPtr
1725				if j == nil {
1726					skip |= skipLen
1727				}
1728				if k == nil {
1729					skip |= skipCap
1730				}
1731			}
1732		}
1733
1734		s.assignWhichMayOverlap(n.X, r, deref, skip, mayOverlap)
1735
1736	case ir.OIF:
1737		n := n.(*ir.IfStmt)
1738		if ir.IsConst(n.Cond, constant.Bool) {
1739			s.stmtList(n.Cond.Init())
1740			if ir.BoolVal(n.Cond) {
1741				s.stmtList(n.Body)
1742			} else {
1743				s.stmtList(n.Else)
1744			}
1745			break
1746		}
1747
1748		bEnd := s.f.NewBlock(ssa.BlockPlain)
1749		var likely int8
1750		if n.Likely {
1751			likely = 1
1752		}
1753		var bThen *ssa.Block
1754		if len(n.Body) != 0 {
1755			bThen = s.f.NewBlock(ssa.BlockPlain)
1756		} else {
1757			bThen = bEnd
1758		}
1759		var bElse *ssa.Block
1760		if len(n.Else) != 0 {
1761			bElse = s.f.NewBlock(ssa.BlockPlain)
1762		} else {
1763			bElse = bEnd
1764		}
1765		s.condBranch(n.Cond, bThen, bElse, likely)
1766
1767		if len(n.Body) != 0 {
1768			s.startBlock(bThen)
1769			s.stmtList(n.Body)
1770			if b := s.endBlock(); b != nil {
1771				b.AddEdgeTo(bEnd)
1772			}
1773		}
1774		if len(n.Else) != 0 {
1775			s.startBlock(bElse)
1776			s.stmtList(n.Else)
1777			if b := s.endBlock(); b != nil {
1778				b.AddEdgeTo(bEnd)
1779			}
1780		}
1781		s.startBlock(bEnd)
1782
1783	case ir.ORETURN:
1784		n := n.(*ir.ReturnStmt)
1785		s.stmtList(n.Results)
1786		b := s.exit()
1787		b.Pos = s.lastPos.WithIsStmt()
1788
1789	case ir.OTAILCALL:
1790		n := n.(*ir.TailCallStmt)
1791		s.callResult(n.Call, callTail)
1792		call := s.mem()
1793		b := s.endBlock()
1794		b.Kind = ssa.BlockRetJmp // could use BlockExit. BlockRetJmp is mostly for clarity.
1795		b.SetControl(call)
1796
1797	case ir.OCONTINUE, ir.OBREAK:
1798		n := n.(*ir.BranchStmt)
1799		var to *ssa.Block
1800		if n.Label == nil {
1801			// plain break/continue
1802			switch n.Op() {
1803			case ir.OCONTINUE:
1804				to = s.continueTo
1805			case ir.OBREAK:
1806				to = s.breakTo
1807			}
1808		} else {
1809			// labeled break/continue; look up the target
1810			sym := n.Label
1811			lab := s.label(sym)
1812			switch n.Op() {
1813			case ir.OCONTINUE:
1814				to = lab.continueTarget
1815			case ir.OBREAK:
1816				to = lab.breakTarget
1817			}
1818		}
1819
1820		b := s.endBlock()
1821		b.Pos = s.lastPos.WithIsStmt() // Do this even if b is an empty block.
1822		b.AddEdgeTo(to)
1823
1824	case ir.OFOR:
1825		// OFOR: for Ninit; Left; Right { Nbody }
1826		// cond (Left); body (Nbody); incr (Right)
1827		n := n.(*ir.ForStmt)
1828		base.Assert(!n.DistinctVars) // Should all be rewritten before escape analysis
1829		bCond := s.f.NewBlock(ssa.BlockPlain)
1830		bBody := s.f.NewBlock(ssa.BlockPlain)
1831		bIncr := s.f.NewBlock(ssa.BlockPlain)
1832		bEnd := s.f.NewBlock(ssa.BlockPlain)
1833
1834		// ensure empty for loops have correct position; issue #30167
1835		bBody.Pos = n.Pos()
1836
1837		// first, jump to condition test
1838		b := s.endBlock()
1839		b.AddEdgeTo(bCond)
1840
1841		// generate code to test condition
1842		s.startBlock(bCond)
1843		if n.Cond != nil {
1844			s.condBranch(n.Cond, bBody, bEnd, 1)
1845		} else {
1846			b := s.endBlock()
1847			b.Kind = ssa.BlockPlain
1848			b.AddEdgeTo(bBody)
1849		}
1850
1851		// set up for continue/break in body
1852		prevContinue := s.continueTo
1853		prevBreak := s.breakTo
1854		s.continueTo = bIncr
1855		s.breakTo = bEnd
1856		var lab *ssaLabel
1857		if sym := n.Label; sym != nil {
1858			// labeled for loop
1859			lab = s.label(sym)
1860			lab.continueTarget = bIncr
1861			lab.breakTarget = bEnd
1862		}
1863
1864		// generate body
1865		s.startBlock(bBody)
1866		s.stmtList(n.Body)
1867
1868		// tear down continue/break
1869		s.continueTo = prevContinue
1870		s.breakTo = prevBreak
1871		if lab != nil {
1872			lab.continueTarget = nil
1873			lab.breakTarget = nil
1874		}
1875
1876		// done with body, goto incr
1877		if b := s.endBlock(); b != nil {
1878			b.AddEdgeTo(bIncr)
1879		}
1880
1881		// generate incr
1882		s.startBlock(bIncr)
1883		if n.Post != nil {
1884			s.stmt(n.Post)
1885		}
1886		if b := s.endBlock(); b != nil {
1887			b.AddEdgeTo(bCond)
1888			// It can happen that bIncr ends in a block containing only VARKILL,
1889			// and that muddles the debugging experience.
1890			if b.Pos == src.NoXPos {
1891				b.Pos = bCond.Pos
1892			}
1893		}
1894
1895		s.startBlock(bEnd)
1896
1897	case ir.OSWITCH, ir.OSELECT:
1898		// These have been mostly rewritten by the front end into their Nbody fields.
1899		// Our main task is to correctly hook up any break statements.
1900		bEnd := s.f.NewBlock(ssa.BlockPlain)
1901
1902		prevBreak := s.breakTo
1903		s.breakTo = bEnd
1904		var sym *types.Sym
1905		var body ir.Nodes
1906		if n.Op() == ir.OSWITCH {
1907			n := n.(*ir.SwitchStmt)
1908			sym = n.Label
1909			body = n.Compiled
1910		} else {
1911			n := n.(*ir.SelectStmt)
1912			sym = n.Label
1913			body = n.Compiled
1914		}
1915
1916		var lab *ssaLabel
1917		if sym != nil {
1918			// labeled
1919			lab = s.label(sym)
1920			lab.breakTarget = bEnd
1921		}
1922
1923		// generate body code
1924		s.stmtList(body)
1925
1926		s.breakTo = prevBreak
1927		if lab != nil {
1928			lab.breakTarget = nil
1929		}
1930
1931		// walk adds explicit OBREAK nodes to the end of all reachable code paths.
1932		// If we still have a current block here, then mark it unreachable.
1933		if s.curBlock != nil {
1934			m := s.mem()
1935			b := s.endBlock()
1936			b.Kind = ssa.BlockExit
1937			b.SetControl(m)
1938		}
1939		s.startBlock(bEnd)
1940
1941	case ir.OJUMPTABLE:
1942		n := n.(*ir.JumpTableStmt)
1943
1944		// Make blocks we'll need.
1945		jt := s.f.NewBlock(ssa.BlockJumpTable)
1946		bEnd := s.f.NewBlock(ssa.BlockPlain)
1947
1948		// The only thing that needs evaluating is the index we're looking up.
1949		idx := s.expr(n.Idx)
1950		unsigned := idx.Type.IsUnsigned()
1951
1952		// Extend so we can do everything in uintptr arithmetic.
1953		t := types.Types[types.TUINTPTR]
1954		idx = s.conv(nil, idx, idx.Type, t)
1955
1956		// The ending condition for the current block decides whether we'll use
1957		// the jump table at all.
1958		// We check that min <= idx <= max and jump around the jump table
1959		// if that test fails.
1960		// We implement min <= idx <= max with 0 <= idx-min <= max-min, because
1961		// we'll need idx-min anyway as the control value for the jump table.
1962		var min, max uint64
1963		if unsigned {
1964			min, _ = constant.Uint64Val(n.Cases[0])
1965			max, _ = constant.Uint64Val(n.Cases[len(n.Cases)-1])
1966		} else {
1967			mn, _ := constant.Int64Val(n.Cases[0])
1968			mx, _ := constant.Int64Val(n.Cases[len(n.Cases)-1])
1969			min = uint64(mn)
1970			max = uint64(mx)
1971		}
1972		// Compare idx-min with max-min, to see if we can use the jump table.
1973		idx = s.newValue2(s.ssaOp(ir.OSUB, t), t, idx, s.uintptrConstant(min))
1974		width := s.uintptrConstant(max - min)
1975		cmp := s.newValue2(s.ssaOp(ir.OLE, t), types.Types[types.TBOOL], idx, width)
1976		b := s.endBlock()
1977		b.Kind = ssa.BlockIf
1978		b.SetControl(cmp)
1979		b.AddEdgeTo(jt)             // in range - use jump table
1980		b.AddEdgeTo(bEnd)           // out of range - no case in the jump table will trigger
1981		b.Likely = ssa.BranchLikely // TODO: assumes missing the table entirely is unlikely. True?
1982
1983		// Build jump table block.
1984		s.startBlock(jt)
1985		jt.Pos = n.Pos()
1986		if base.Flag.Cfg.SpectreIndex {
1987			idx = s.newValue2(ssa.OpSpectreSliceIndex, t, idx, width)
1988		}
1989		jt.SetControl(idx)
1990
1991		// Figure out where we should go for each index in the table.
1992		table := make([]*ssa.Block, max-min+1)
1993		for i := range table {
1994			table[i] = bEnd // default target
1995		}
1996		for i := range n.Targets {
1997			c := n.Cases[i]
1998			lab := s.label(n.Targets[i])
1999			if lab.target == nil {
2000				lab.target = s.f.NewBlock(ssa.BlockPlain)
2001			}
2002			var val uint64
2003			if unsigned {
2004				val, _ = constant.Uint64Val(c)
2005			} else {
2006				vl, _ := constant.Int64Val(c)
2007				val = uint64(vl)
2008			}
2009			// Overwrite the default target.
2010			table[val-min] = lab.target
2011		}
2012		for _, t := range table {
2013			jt.AddEdgeTo(t)
2014		}
2015		s.endBlock()
2016
2017		s.startBlock(bEnd)
2018
2019	case ir.OINTERFACESWITCH:
2020		n := n.(*ir.InterfaceSwitchStmt)
2021		typs := s.f.Config.Types
2022
2023		t := s.expr(n.RuntimeType)
2024		h := s.expr(n.Hash)
2025		d := s.newValue1A(ssa.OpAddr, typs.BytePtr, n.Descriptor, s.sb)
2026
2027		// Check the cache first.
2028		var merge *ssa.Block
2029		if base.Flag.N == 0 && rtabi.UseInterfaceSwitchCache(Arch.LinkArch.Name) {
2030			// Note: we can only use the cache if we have the right atomic load instruction.
2031			// Double-check that here.
2032			if _, ok := intrinsics[intrinsicKey{Arch.LinkArch.Arch, "internal/runtime/atomic", "Loadp"}]; !ok {
2033				s.Fatalf("atomic load not available")
2034			}
2035			merge = s.f.NewBlock(ssa.BlockPlain)
2036			cacheHit := s.f.NewBlock(ssa.BlockPlain)
2037			cacheMiss := s.f.NewBlock(ssa.BlockPlain)
2038			loopHead := s.f.NewBlock(ssa.BlockPlain)
2039			loopBody := s.f.NewBlock(ssa.BlockPlain)
2040
2041			// Pick right size ops.
2042			var mul, and, add, zext ssa.Op
2043			if s.config.PtrSize == 4 {
2044				mul = ssa.OpMul32
2045				and = ssa.OpAnd32
2046				add = ssa.OpAdd32
2047				zext = ssa.OpCopy
2048			} else {
2049				mul = ssa.OpMul64
2050				and = ssa.OpAnd64
2051				add = ssa.OpAdd64
2052				zext = ssa.OpZeroExt32to64
2053			}
2054
2055			// Load cache pointer out of descriptor, with an atomic load so
2056			// we ensure that we see a fully written cache.
2057			atomicLoad := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(typs.BytePtr, types.TypeMem), d, s.mem())
2058			cache := s.newValue1(ssa.OpSelect0, typs.BytePtr, atomicLoad)
2059			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, atomicLoad)
2060
2061			// Initialize hash variable.
2062			s.vars[hashVar] = s.newValue1(zext, typs.Uintptr, h)
2063
2064			// Load mask from cache.
2065			mask := s.newValue2(ssa.OpLoad, typs.Uintptr, cache, s.mem())
2066			// Jump to loop head.
2067			b := s.endBlock()
2068			b.AddEdgeTo(loopHead)
2069
2070			// At loop head, get pointer to the cache entry.
2071			//   e := &cache.Entries[hash&mask]
2072			s.startBlock(loopHead)
2073			entries := s.newValue2(ssa.OpAddPtr, typs.UintptrPtr, cache, s.uintptrConstant(uint64(s.config.PtrSize)))
2074			idx := s.newValue2(and, typs.Uintptr, s.variable(hashVar, typs.Uintptr), mask)
2075			idx = s.newValue2(mul, typs.Uintptr, idx, s.uintptrConstant(uint64(3*s.config.PtrSize)))
2076			e := s.newValue2(ssa.OpAddPtr, typs.UintptrPtr, entries, idx)
2077			//   hash++
2078			s.vars[hashVar] = s.newValue2(add, typs.Uintptr, s.variable(hashVar, typs.Uintptr), s.uintptrConstant(1))
2079
2080			// Look for a cache hit.
2081			//   if e.Typ == t { goto hit }
2082			eTyp := s.newValue2(ssa.OpLoad, typs.Uintptr, e, s.mem())
2083			cmp1 := s.newValue2(ssa.OpEqPtr, typs.Bool, t, eTyp)
2084			b = s.endBlock()
2085			b.Kind = ssa.BlockIf
2086			b.SetControl(cmp1)
2087			b.AddEdgeTo(cacheHit)
2088			b.AddEdgeTo(loopBody)
2089
2090			// Look for an empty entry, the tombstone for this hash table.
2091			//   if e.Typ == nil { goto miss }
2092			s.startBlock(loopBody)
2093			cmp2 := s.newValue2(ssa.OpEqPtr, typs.Bool, eTyp, s.constNil(typs.BytePtr))
2094			b = s.endBlock()
2095			b.Kind = ssa.BlockIf
2096			b.SetControl(cmp2)
2097			b.AddEdgeTo(cacheMiss)
2098			b.AddEdgeTo(loopHead)
2099
2100			// On a hit, load the data fields of the cache entry.
2101			//   Case = e.Case
2102			//   Itab = e.Itab
2103			s.startBlock(cacheHit)
2104			eCase := s.newValue2(ssa.OpLoad, typs.Int, s.newValue1I(ssa.OpOffPtr, typs.IntPtr, s.config.PtrSize, e), s.mem())
2105			eItab := s.newValue2(ssa.OpLoad, typs.BytePtr, s.newValue1I(ssa.OpOffPtr, typs.BytePtrPtr, 2*s.config.PtrSize, e), s.mem())
2106			s.assign(n.Case, eCase, false, 0)
2107			s.assign(n.Itab, eItab, false, 0)
2108			b = s.endBlock()
2109			b.AddEdgeTo(merge)
2110
2111			// On a miss, call into the runtime to get the answer.
2112			s.startBlock(cacheMiss)
2113		}
2114
2115		r := s.rtcall(ir.Syms.InterfaceSwitch, true, []*types.Type{typs.Int, typs.BytePtr}, d, t)
2116		s.assign(n.Case, r[0], false, 0)
2117		s.assign(n.Itab, r[1], false, 0)
2118
2119		if merge != nil {
2120			// Cache hits merge in here.
2121			b := s.endBlock()
2122			b.Kind = ssa.BlockPlain
2123			b.AddEdgeTo(merge)
2124			s.startBlock(merge)
2125		}
2126
2127	case ir.OCHECKNIL:
2128		n := n.(*ir.UnaryExpr)
2129		p := s.expr(n.X)
2130		_ = s.nilCheck(p)
2131		// TODO: check that throwing away the nilcheck result is ok.
2132
2133	case ir.OINLMARK:
2134		n := n.(*ir.InlineMarkStmt)
2135		s.newValue1I(ssa.OpInlMark, types.TypeVoid, n.Index, s.mem())
2136
2137	default:
2138		s.Fatalf("unhandled stmt %v", n.Op())
2139	}
2140}
2141
2142// If true, share as many open-coded defer exits as possible (with the downside of
2143// worse line-number information)
2144const shareDeferExits = false
2145
2146// exit processes any code that needs to be generated just before returning.
2147// It returns a BlockRet block that ends the control flow. Its control value
2148// will be set to the final memory state.
2149func (s *state) exit() *ssa.Block {
2150	if s.hasdefer {
2151		if s.hasOpenDefers {
2152			if shareDeferExits && s.lastDeferExit != nil && len(s.openDefers) == s.lastDeferCount {
2153				if s.curBlock.Kind != ssa.BlockPlain {
2154					panic("Block for an exit should be BlockPlain")
2155				}
2156				s.curBlock.AddEdgeTo(s.lastDeferExit)
2157				s.endBlock()
2158				return s.lastDeferFinalBlock
2159			}
2160			s.openDeferExit()
2161		} else {
2162			s.rtcall(ir.Syms.Deferreturn, true, nil)
2163		}
2164	}
2165
2166	// Do actual return.
2167	// These currently turn into self-copies (in many cases).
2168	resultFields := s.curfn.Type().Results()
2169	results := make([]*ssa.Value, len(resultFields)+1, len(resultFields)+1)
2170	// Store SSAable and heap-escaped PPARAMOUT variables back to stack locations.
2171	for i, f := range resultFields {
2172		n := f.Nname.(*ir.Name)
2173		if s.canSSA(n) { // result is in some SSA variable
2174			if !n.IsOutputParamInRegisters() && n.Type().HasPointers() {
2175				// We are about to store to the result slot.
2176				s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
2177			}
2178			results[i] = s.variable(n, n.Type())
2179		} else if !n.OnStack() { // result is actually heap allocated
2180			// We are about to copy the in-heap result to the result slot.
2181			if n.Type().HasPointers() {
2182				s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
2183			}
2184			ha := s.expr(n.Heapaddr)
2185			s.instrumentFields(n.Type(), ha, instrumentRead)
2186			results[i] = s.newValue2(ssa.OpDereference, n.Type(), ha, s.mem())
2187		} else { // result is not SSA-able; not escaped, so not on heap, but too large for SSA.
2188			// Before register ABI this ought to be a self-move, home=dest,
2189			// With register ABI, it's still a self-move if parameter is on stack (i.e., too big or overflowed)
2190			// No VarDef, as the result slot is already holding live value.
2191			results[i] = s.newValue2(ssa.OpDereference, n.Type(), s.addr(n), s.mem())
2192		}
2193	}
2194
2195	// In -race mode, we need to call racefuncexit.
2196	// Note: This has to happen after we load any heap-allocated results,
2197	// otherwise races will be attributed to the caller instead.
2198	if s.instrumentEnterExit {
2199		s.rtcall(ir.Syms.Racefuncexit, true, nil)
2200	}
2201
2202	results[len(results)-1] = s.mem()
2203	m := s.newValue0(ssa.OpMakeResult, s.f.OwnAux.LateExpansionResultType())
2204	m.AddArgs(results...)
2205
2206	b := s.endBlock()
2207	b.Kind = ssa.BlockRet
2208	b.SetControl(m)
2209	if s.hasdefer && s.hasOpenDefers {
2210		s.lastDeferFinalBlock = b
2211	}
2212	return b
2213}
2214
2215type opAndType struct {
2216	op    ir.Op
2217	etype types.Kind
2218}
2219
2220var opToSSA = map[opAndType]ssa.Op{
2221	{ir.OADD, types.TINT8}:    ssa.OpAdd8,
2222	{ir.OADD, types.TUINT8}:   ssa.OpAdd8,
2223	{ir.OADD, types.TINT16}:   ssa.OpAdd16,
2224	{ir.OADD, types.TUINT16}:  ssa.OpAdd16,
2225	{ir.OADD, types.TINT32}:   ssa.OpAdd32,
2226	{ir.OADD, types.TUINT32}:  ssa.OpAdd32,
2227	{ir.OADD, types.TINT64}:   ssa.OpAdd64,
2228	{ir.OADD, types.TUINT64}:  ssa.OpAdd64,
2229	{ir.OADD, types.TFLOAT32}: ssa.OpAdd32F,
2230	{ir.OADD, types.TFLOAT64}: ssa.OpAdd64F,
2231
2232	{ir.OSUB, types.TINT8}:    ssa.OpSub8,
2233	{ir.OSUB, types.TUINT8}:   ssa.OpSub8,
2234	{ir.OSUB, types.TINT16}:   ssa.OpSub16,
2235	{ir.OSUB, types.TUINT16}:  ssa.OpSub16,
2236	{ir.OSUB, types.TINT32}:   ssa.OpSub32,
2237	{ir.OSUB, types.TUINT32}:  ssa.OpSub32,
2238	{ir.OSUB, types.TINT64}:   ssa.OpSub64,
2239	{ir.OSUB, types.TUINT64}:  ssa.OpSub64,
2240	{ir.OSUB, types.TFLOAT32}: ssa.OpSub32F,
2241	{ir.OSUB, types.TFLOAT64}: ssa.OpSub64F,
2242
2243	{ir.ONOT, types.TBOOL}: ssa.OpNot,
2244
2245	{ir.ONEG, types.TINT8}:    ssa.OpNeg8,
2246	{ir.ONEG, types.TUINT8}:   ssa.OpNeg8,
2247	{ir.ONEG, types.TINT16}:   ssa.OpNeg16,
2248	{ir.ONEG, types.TUINT16}:  ssa.OpNeg16,
2249	{ir.ONEG, types.TINT32}:   ssa.OpNeg32,
2250	{ir.ONEG, types.TUINT32}:  ssa.OpNeg32,
2251	{ir.ONEG, types.TINT64}:   ssa.OpNeg64,
2252	{ir.ONEG, types.TUINT64}:  ssa.OpNeg64,
2253	{ir.ONEG, types.TFLOAT32}: ssa.OpNeg32F,
2254	{ir.ONEG, types.TFLOAT64}: ssa.OpNeg64F,
2255
2256	{ir.OBITNOT, types.TINT8}:   ssa.OpCom8,
2257	{ir.OBITNOT, types.TUINT8}:  ssa.OpCom8,
2258	{ir.OBITNOT, types.TINT16}:  ssa.OpCom16,
2259	{ir.OBITNOT, types.TUINT16}: ssa.OpCom16,
2260	{ir.OBITNOT, types.TINT32}:  ssa.OpCom32,
2261	{ir.OBITNOT, types.TUINT32}: ssa.OpCom32,
2262	{ir.OBITNOT, types.TINT64}:  ssa.OpCom64,
2263	{ir.OBITNOT, types.TUINT64}: ssa.OpCom64,
2264
2265	{ir.OIMAG, types.TCOMPLEX64}:  ssa.OpComplexImag,
2266	{ir.OIMAG, types.TCOMPLEX128}: ssa.OpComplexImag,
2267	{ir.OREAL, types.TCOMPLEX64}:  ssa.OpComplexReal,
2268	{ir.OREAL, types.TCOMPLEX128}: ssa.OpComplexReal,
2269
2270	{ir.OMUL, types.TINT8}:    ssa.OpMul8,
2271	{ir.OMUL, types.TUINT8}:   ssa.OpMul8,
2272	{ir.OMUL, types.TINT16}:   ssa.OpMul16,
2273	{ir.OMUL, types.TUINT16}:  ssa.OpMul16,
2274	{ir.OMUL, types.TINT32}:   ssa.OpMul32,
2275	{ir.OMUL, types.TUINT32}:  ssa.OpMul32,
2276	{ir.OMUL, types.TINT64}:   ssa.OpMul64,
2277	{ir.OMUL, types.TUINT64}:  ssa.OpMul64,
2278	{ir.OMUL, types.TFLOAT32}: ssa.OpMul32F,
2279	{ir.OMUL, types.TFLOAT64}: ssa.OpMul64F,
2280
2281	{ir.ODIV, types.TFLOAT32}: ssa.OpDiv32F,
2282	{ir.ODIV, types.TFLOAT64}: ssa.OpDiv64F,
2283
2284	{ir.ODIV, types.TINT8}:   ssa.OpDiv8,
2285	{ir.ODIV, types.TUINT8}:  ssa.OpDiv8u,
2286	{ir.ODIV, types.TINT16}:  ssa.OpDiv16,
2287	{ir.ODIV, types.TUINT16}: ssa.OpDiv16u,
2288	{ir.ODIV, types.TINT32}:  ssa.OpDiv32,
2289	{ir.ODIV, types.TUINT32}: ssa.OpDiv32u,
2290	{ir.ODIV, types.TINT64}:  ssa.OpDiv64,
2291	{ir.ODIV, types.TUINT64}: ssa.OpDiv64u,
2292
2293	{ir.OMOD, types.TINT8}:   ssa.OpMod8,
2294	{ir.OMOD, types.TUINT8}:  ssa.OpMod8u,
2295	{ir.OMOD, types.TINT16}:  ssa.OpMod16,
2296	{ir.OMOD, types.TUINT16}: ssa.OpMod16u,
2297	{ir.OMOD, types.TINT32}:  ssa.OpMod32,
2298	{ir.OMOD, types.TUINT32}: ssa.OpMod32u,
2299	{ir.OMOD, types.TINT64}:  ssa.OpMod64,
2300	{ir.OMOD, types.TUINT64}: ssa.OpMod64u,
2301
2302	{ir.OAND, types.TINT8}:   ssa.OpAnd8,
2303	{ir.OAND, types.TUINT8}:  ssa.OpAnd8,
2304	{ir.OAND, types.TINT16}:  ssa.OpAnd16,
2305	{ir.OAND, types.TUINT16}: ssa.OpAnd16,
2306	{ir.OAND, types.TINT32}:  ssa.OpAnd32,
2307	{ir.OAND, types.TUINT32}: ssa.OpAnd32,
2308	{ir.OAND, types.TINT64}:  ssa.OpAnd64,
2309	{ir.OAND, types.TUINT64}: ssa.OpAnd64,
2310
2311	{ir.OOR, types.TINT8}:   ssa.OpOr8,
2312	{ir.OOR, types.TUINT8}:  ssa.OpOr8,
2313	{ir.OOR, types.TINT16}:  ssa.OpOr16,
2314	{ir.OOR, types.TUINT16}: ssa.OpOr16,
2315	{ir.OOR, types.TINT32}:  ssa.OpOr32,
2316	{ir.OOR, types.TUINT32}: ssa.OpOr32,
2317	{ir.OOR, types.TINT64}:  ssa.OpOr64,
2318	{ir.OOR, types.TUINT64}: ssa.OpOr64,
2319
2320	{ir.OXOR, types.TINT8}:   ssa.OpXor8,
2321	{ir.OXOR, types.TUINT8}:  ssa.OpXor8,
2322	{ir.OXOR, types.TINT16}:  ssa.OpXor16,
2323	{ir.OXOR, types.TUINT16}: ssa.OpXor16,
2324	{ir.OXOR, types.TINT32}:  ssa.OpXor32,
2325	{ir.OXOR, types.TUINT32}: ssa.OpXor32,
2326	{ir.OXOR, types.TINT64}:  ssa.OpXor64,
2327	{ir.OXOR, types.TUINT64}: ssa.OpXor64,
2328
2329	{ir.OEQ, types.TBOOL}:      ssa.OpEqB,
2330	{ir.OEQ, types.TINT8}:      ssa.OpEq8,
2331	{ir.OEQ, types.TUINT8}:     ssa.OpEq8,
2332	{ir.OEQ, types.TINT16}:     ssa.OpEq16,
2333	{ir.OEQ, types.TUINT16}:    ssa.OpEq16,
2334	{ir.OEQ, types.TINT32}:     ssa.OpEq32,
2335	{ir.OEQ, types.TUINT32}:    ssa.OpEq32,
2336	{ir.OEQ, types.TINT64}:     ssa.OpEq64,
2337	{ir.OEQ, types.TUINT64}:    ssa.OpEq64,
2338	{ir.OEQ, types.TINTER}:     ssa.OpEqInter,
2339	{ir.OEQ, types.TSLICE}:     ssa.OpEqSlice,
2340	{ir.OEQ, types.TFUNC}:      ssa.OpEqPtr,
2341	{ir.OEQ, types.TMAP}:       ssa.OpEqPtr,
2342	{ir.OEQ, types.TCHAN}:      ssa.OpEqPtr,
2343	{ir.OEQ, types.TPTR}:       ssa.OpEqPtr,
2344	{ir.OEQ, types.TUINTPTR}:   ssa.OpEqPtr,
2345	{ir.OEQ, types.TUNSAFEPTR}: ssa.OpEqPtr,
2346	{ir.OEQ, types.TFLOAT64}:   ssa.OpEq64F,
2347	{ir.OEQ, types.TFLOAT32}:   ssa.OpEq32F,
2348
2349	{ir.ONE, types.TBOOL}:      ssa.OpNeqB,
2350	{ir.ONE, types.TINT8}:      ssa.OpNeq8,
2351	{ir.ONE, types.TUINT8}:     ssa.OpNeq8,
2352	{ir.ONE, types.TINT16}:     ssa.OpNeq16,
2353	{ir.ONE, types.TUINT16}:    ssa.OpNeq16,
2354	{ir.ONE, types.TINT32}:     ssa.OpNeq32,
2355	{ir.ONE, types.TUINT32}:    ssa.OpNeq32,
2356	{ir.ONE, types.TINT64}:     ssa.OpNeq64,
2357	{ir.ONE, types.TUINT64}:    ssa.OpNeq64,
2358	{ir.ONE, types.TINTER}:     ssa.OpNeqInter,
2359	{ir.ONE, types.TSLICE}:     ssa.OpNeqSlice,
2360	{ir.ONE, types.TFUNC}:      ssa.OpNeqPtr,
2361	{ir.ONE, types.TMAP}:       ssa.OpNeqPtr,
2362	{ir.ONE, types.TCHAN}:      ssa.OpNeqPtr,
2363	{ir.ONE, types.TPTR}:       ssa.OpNeqPtr,
2364	{ir.ONE, types.TUINTPTR}:   ssa.OpNeqPtr,
2365	{ir.ONE, types.TUNSAFEPTR}: ssa.OpNeqPtr,
2366	{ir.ONE, types.TFLOAT64}:   ssa.OpNeq64F,
2367	{ir.ONE, types.TFLOAT32}:   ssa.OpNeq32F,
2368
2369	{ir.OLT, types.TINT8}:    ssa.OpLess8,
2370	{ir.OLT, types.TUINT8}:   ssa.OpLess8U,
2371	{ir.OLT, types.TINT16}:   ssa.OpLess16,
2372	{ir.OLT, types.TUINT16}:  ssa.OpLess16U,
2373	{ir.OLT, types.TINT32}:   ssa.OpLess32,
2374	{ir.OLT, types.TUINT32}:  ssa.OpLess32U,
2375	{ir.OLT, types.TINT64}:   ssa.OpLess64,
2376	{ir.OLT, types.TUINT64}:  ssa.OpLess64U,
2377	{ir.OLT, types.TFLOAT64}: ssa.OpLess64F,
2378	{ir.OLT, types.TFLOAT32}: ssa.OpLess32F,
2379
2380	{ir.OLE, types.TINT8}:    ssa.OpLeq8,
2381	{ir.OLE, types.TUINT8}:   ssa.OpLeq8U,
2382	{ir.OLE, types.TINT16}:   ssa.OpLeq16,
2383	{ir.OLE, types.TUINT16}:  ssa.OpLeq16U,
2384	{ir.OLE, types.TINT32}:   ssa.OpLeq32,
2385	{ir.OLE, types.TUINT32}:  ssa.OpLeq32U,
2386	{ir.OLE, types.TINT64}:   ssa.OpLeq64,
2387	{ir.OLE, types.TUINT64}:  ssa.OpLeq64U,
2388	{ir.OLE, types.TFLOAT64}: ssa.OpLeq64F,
2389	{ir.OLE, types.TFLOAT32}: ssa.OpLeq32F,
2390}
2391
2392func (s *state) concreteEtype(t *types.Type) types.Kind {
2393	e := t.Kind()
2394	switch e {
2395	default:
2396		return e
2397	case types.TINT:
2398		if s.config.PtrSize == 8 {
2399			return types.TINT64
2400		}
2401		return types.TINT32
2402	case types.TUINT:
2403		if s.config.PtrSize == 8 {
2404			return types.TUINT64
2405		}
2406		return types.TUINT32
2407	case types.TUINTPTR:
2408		if s.config.PtrSize == 8 {
2409			return types.TUINT64
2410		}
2411		return types.TUINT32
2412	}
2413}
2414
2415func (s *state) ssaOp(op ir.Op, t *types.Type) ssa.Op {
2416	etype := s.concreteEtype(t)
2417	x, ok := opToSSA[opAndType{op, etype}]
2418	if !ok {
2419		s.Fatalf("unhandled binary op %v %s", op, etype)
2420	}
2421	return x
2422}
2423
2424type opAndTwoTypes struct {
2425	op     ir.Op
2426	etype1 types.Kind
2427	etype2 types.Kind
2428}
2429
2430type twoTypes struct {
2431	etype1 types.Kind
2432	etype2 types.Kind
2433}
2434
2435type twoOpsAndType struct {
2436	op1              ssa.Op
2437	op2              ssa.Op
2438	intermediateType types.Kind
2439}
2440
2441var fpConvOpToSSA = map[twoTypes]twoOpsAndType{
2442
2443	{types.TINT8, types.TFLOAT32}:  {ssa.OpSignExt8to32, ssa.OpCvt32to32F, types.TINT32},
2444	{types.TINT16, types.TFLOAT32}: {ssa.OpSignExt16to32, ssa.OpCvt32to32F, types.TINT32},
2445	{types.TINT32, types.TFLOAT32}: {ssa.OpCopy, ssa.OpCvt32to32F, types.TINT32},
2446	{types.TINT64, types.TFLOAT32}: {ssa.OpCopy, ssa.OpCvt64to32F, types.TINT64},
2447
2448	{types.TINT8, types.TFLOAT64}:  {ssa.OpSignExt8to32, ssa.OpCvt32to64F, types.TINT32},
2449	{types.TINT16, types.TFLOAT64}: {ssa.OpSignExt16to32, ssa.OpCvt32to64F, types.TINT32},
2450	{types.TINT32, types.TFLOAT64}: {ssa.OpCopy, ssa.OpCvt32to64F, types.TINT32},
2451	{types.TINT64, types.TFLOAT64}: {ssa.OpCopy, ssa.OpCvt64to64F, types.TINT64},
2452
2453	{types.TFLOAT32, types.TINT8}:  {ssa.OpCvt32Fto32, ssa.OpTrunc32to8, types.TINT32},
2454	{types.TFLOAT32, types.TINT16}: {ssa.OpCvt32Fto32, ssa.OpTrunc32to16, types.TINT32},
2455	{types.TFLOAT32, types.TINT32}: {ssa.OpCvt32Fto32, ssa.OpCopy, types.TINT32},
2456	{types.TFLOAT32, types.TINT64}: {ssa.OpCvt32Fto64, ssa.OpCopy, types.TINT64},
2457
2458	{types.TFLOAT64, types.TINT8}:  {ssa.OpCvt64Fto32, ssa.OpTrunc32to8, types.TINT32},
2459	{types.TFLOAT64, types.TINT16}: {ssa.OpCvt64Fto32, ssa.OpTrunc32to16, types.TINT32},
2460	{types.TFLOAT64, types.TINT32}: {ssa.OpCvt64Fto32, ssa.OpCopy, types.TINT32},
2461	{types.TFLOAT64, types.TINT64}: {ssa.OpCvt64Fto64, ssa.OpCopy, types.TINT64},
2462	// unsigned
2463	{types.TUINT8, types.TFLOAT32}:  {ssa.OpZeroExt8to32, ssa.OpCvt32to32F, types.TINT32},
2464	{types.TUINT16, types.TFLOAT32}: {ssa.OpZeroExt16to32, ssa.OpCvt32to32F, types.TINT32},
2465	{types.TUINT32, types.TFLOAT32}: {ssa.OpZeroExt32to64, ssa.OpCvt64to32F, types.TINT64}, // go wide to dodge unsigned
2466	{types.TUINT64, types.TFLOAT32}: {ssa.OpCopy, ssa.OpInvalid, types.TUINT64},            // Cvt64Uto32F, branchy code expansion instead
2467
2468	{types.TUINT8, types.TFLOAT64}:  {ssa.OpZeroExt8to32, ssa.OpCvt32to64F, types.TINT32},
2469	{types.TUINT16, types.TFLOAT64}: {ssa.OpZeroExt16to32, ssa.OpCvt32to64F, types.TINT32},
2470	{types.TUINT32, types.TFLOAT64}: {ssa.OpZeroExt32to64, ssa.OpCvt64to64F, types.TINT64}, // go wide to dodge unsigned
2471	{types.TUINT64, types.TFLOAT64}: {ssa.OpCopy, ssa.OpInvalid, types.TUINT64},            // Cvt64Uto64F, branchy code expansion instead
2472
2473	{types.TFLOAT32, types.TUINT8}:  {ssa.OpCvt32Fto32, ssa.OpTrunc32to8, types.TINT32},
2474	{types.TFLOAT32, types.TUINT16}: {ssa.OpCvt32Fto32, ssa.OpTrunc32to16, types.TINT32},
2475	{types.TFLOAT32, types.TUINT32}: {ssa.OpCvt32Fto64, ssa.OpTrunc64to32, types.TINT64}, // go wide to dodge unsigned
2476	{types.TFLOAT32, types.TUINT64}: {ssa.OpInvalid, ssa.OpCopy, types.TUINT64},          // Cvt32Fto64U, branchy code expansion instead
2477
2478	{types.TFLOAT64, types.TUINT8}:  {ssa.OpCvt64Fto32, ssa.OpTrunc32to8, types.TINT32},
2479	{types.TFLOAT64, types.TUINT16}: {ssa.OpCvt64Fto32, ssa.OpTrunc32to16, types.TINT32},
2480	{types.TFLOAT64, types.TUINT32}: {ssa.OpCvt64Fto64, ssa.OpTrunc64to32, types.TINT64}, // go wide to dodge unsigned
2481	{types.TFLOAT64, types.TUINT64}: {ssa.OpInvalid, ssa.OpCopy, types.TUINT64},          // Cvt64Fto64U, branchy code expansion instead
2482
2483	// float
2484	{types.TFLOAT64, types.TFLOAT32}: {ssa.OpCvt64Fto32F, ssa.OpCopy, types.TFLOAT32},
2485	{types.TFLOAT64, types.TFLOAT64}: {ssa.OpRound64F, ssa.OpCopy, types.TFLOAT64},
2486	{types.TFLOAT32, types.TFLOAT32}: {ssa.OpRound32F, ssa.OpCopy, types.TFLOAT32},
2487	{types.TFLOAT32, types.TFLOAT64}: {ssa.OpCvt32Fto64F, ssa.OpCopy, types.TFLOAT64},
2488}
2489
2490// this map is used only for 32-bit arch, and only includes the difference
2491// on 32-bit arch, don't use int64<->float conversion for uint32
2492var fpConvOpToSSA32 = map[twoTypes]twoOpsAndType{
2493	{types.TUINT32, types.TFLOAT32}: {ssa.OpCopy, ssa.OpCvt32Uto32F, types.TUINT32},
2494	{types.TUINT32, types.TFLOAT64}: {ssa.OpCopy, ssa.OpCvt32Uto64F, types.TUINT32},
2495	{types.TFLOAT32, types.TUINT32}: {ssa.OpCvt32Fto32U, ssa.OpCopy, types.TUINT32},
2496	{types.TFLOAT64, types.TUINT32}: {ssa.OpCvt64Fto32U, ssa.OpCopy, types.TUINT32},
2497}
2498
2499// uint64<->float conversions, only on machines that have instructions for that
2500var uint64fpConvOpToSSA = map[twoTypes]twoOpsAndType{
2501	{types.TUINT64, types.TFLOAT32}: {ssa.OpCopy, ssa.OpCvt64Uto32F, types.TUINT64},
2502	{types.TUINT64, types.TFLOAT64}: {ssa.OpCopy, ssa.OpCvt64Uto64F, types.TUINT64},
2503	{types.TFLOAT32, types.TUINT64}: {ssa.OpCvt32Fto64U, ssa.OpCopy, types.TUINT64},
2504	{types.TFLOAT64, types.TUINT64}: {ssa.OpCvt64Fto64U, ssa.OpCopy, types.TUINT64},
2505}
2506
2507var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{
2508	{ir.OLSH, types.TINT8, types.TUINT8}:   ssa.OpLsh8x8,
2509	{ir.OLSH, types.TUINT8, types.TUINT8}:  ssa.OpLsh8x8,
2510	{ir.OLSH, types.TINT8, types.TUINT16}:  ssa.OpLsh8x16,
2511	{ir.OLSH, types.TUINT8, types.TUINT16}: ssa.OpLsh8x16,
2512	{ir.OLSH, types.TINT8, types.TUINT32}:  ssa.OpLsh8x32,
2513	{ir.OLSH, types.TUINT8, types.TUINT32}: ssa.OpLsh8x32,
2514	{ir.OLSH, types.TINT8, types.TUINT64}:  ssa.OpLsh8x64,
2515	{ir.OLSH, types.TUINT8, types.TUINT64}: ssa.OpLsh8x64,
2516
2517	{ir.OLSH, types.TINT16, types.TUINT8}:   ssa.OpLsh16x8,
2518	{ir.OLSH, types.TUINT16, types.TUINT8}:  ssa.OpLsh16x8,
2519	{ir.OLSH, types.TINT16, types.TUINT16}:  ssa.OpLsh16x16,
2520	{ir.OLSH, types.TUINT16, types.TUINT16}: ssa.OpLsh16x16,
2521	{ir.OLSH, types.TINT16, types.TUINT32}:  ssa.OpLsh16x32,
2522	{ir.OLSH, types.TUINT16, types.TUINT32}: ssa.OpLsh16x32,
2523	{ir.OLSH, types.TINT16, types.TUINT64}:  ssa.OpLsh16x64,
2524	{ir.OLSH, types.TUINT16, types.TUINT64}: ssa.OpLsh16x64,
2525
2526	{ir.OLSH, types.TINT32, types.TUINT8}:   ssa.OpLsh32x8,
2527	{ir.OLSH, types.TUINT32, types.TUINT8}:  ssa.OpLsh32x8,
2528	{ir.OLSH, types.TINT32, types.TUINT16}:  ssa.OpLsh32x16,
2529	{ir.OLSH, types.TUINT32, types.TUINT16}: ssa.OpLsh32x16,
2530	{ir.OLSH, types.TINT32, types.TUINT32}:  ssa.OpLsh32x32,
2531	{ir.OLSH, types.TUINT32, types.TUINT32}: ssa.OpLsh32x32,
2532	{ir.OLSH, types.TINT32, types.TUINT64}:  ssa.OpLsh32x64,
2533	{ir.OLSH, types.TUINT32, types.TUINT64}: ssa.OpLsh32x64,
2534
2535	{ir.OLSH, types.TINT64, types.TUINT8}:   ssa.OpLsh64x8,
2536	{ir.OLSH, types.TUINT64, types.TUINT8}:  ssa.OpLsh64x8,
2537	{ir.OLSH, types.TINT64, types.TUINT16}:  ssa.OpLsh64x16,
2538	{ir.OLSH, types.TUINT64, types.TUINT16}: ssa.OpLsh64x16,
2539	{ir.OLSH, types.TINT64, types.TUINT32}:  ssa.OpLsh64x32,
2540	{ir.OLSH, types.TUINT64, types.TUINT32}: ssa.OpLsh64x32,
2541	{ir.OLSH, types.TINT64, types.TUINT64}:  ssa.OpLsh64x64,
2542	{ir.OLSH, types.TUINT64, types.TUINT64}: ssa.OpLsh64x64,
2543
2544	{ir.ORSH, types.TINT8, types.TUINT8}:   ssa.OpRsh8x8,
2545	{ir.ORSH, types.TUINT8, types.TUINT8}:  ssa.OpRsh8Ux8,
2546	{ir.ORSH, types.TINT8, types.TUINT16}:  ssa.OpRsh8x16,
2547	{ir.ORSH, types.TUINT8, types.TUINT16}: ssa.OpRsh8Ux16,
2548	{ir.ORSH, types.TINT8, types.TUINT32}:  ssa.OpRsh8x32,
2549	{ir.ORSH, types.TUINT8, types.TUINT32}: ssa.OpRsh8Ux32,
2550	{ir.ORSH, types.TINT8, types.TUINT64}:  ssa.OpRsh8x64,
2551	{ir.ORSH, types.TUINT8, types.TUINT64}: ssa.OpRsh8Ux64,
2552
2553	{ir.ORSH, types.TINT16, types.TUINT8}:   ssa.OpRsh16x8,
2554	{ir.ORSH, types.TUINT16, types.TUINT8}:  ssa.OpRsh16Ux8,
2555	{ir.ORSH, types.TINT16, types.TUINT16}:  ssa.OpRsh16x16,
2556	{ir.ORSH, types.TUINT16, types.TUINT16}: ssa.OpRsh16Ux16,
2557	{ir.ORSH, types.TINT16, types.TUINT32}:  ssa.OpRsh16x32,
2558	{ir.ORSH, types.TUINT16, types.TUINT32}: ssa.OpRsh16Ux32,
2559	{ir.ORSH, types.TINT16, types.TUINT64}:  ssa.OpRsh16x64,
2560	{ir.ORSH, types.TUINT16, types.TUINT64}: ssa.OpRsh16Ux64,
2561
2562	{ir.ORSH, types.TINT32, types.TUINT8}:   ssa.OpRsh32x8,
2563	{ir.ORSH, types.TUINT32, types.TUINT8}:  ssa.OpRsh32Ux8,
2564	{ir.ORSH, types.TINT32, types.TUINT16}:  ssa.OpRsh32x16,
2565	{ir.ORSH, types.TUINT32, types.TUINT16}: ssa.OpRsh32Ux16,
2566	{ir.ORSH, types.TINT32, types.TUINT32}:  ssa.OpRsh32x32,
2567	{ir.ORSH, types.TUINT32, types.TUINT32}: ssa.OpRsh32Ux32,
2568	{ir.ORSH, types.TINT32, types.TUINT64}:  ssa.OpRsh32x64,
2569	{ir.ORSH, types.TUINT32, types.TUINT64}: ssa.OpRsh32Ux64,
2570
2571	{ir.ORSH, types.TINT64, types.TUINT8}:   ssa.OpRsh64x8,
2572	{ir.ORSH, types.TUINT64, types.TUINT8}:  ssa.OpRsh64Ux8,
2573	{ir.ORSH, types.TINT64, types.TUINT16}:  ssa.OpRsh64x16,
2574	{ir.ORSH, types.TUINT64, types.TUINT16}: ssa.OpRsh64Ux16,
2575	{ir.ORSH, types.TINT64, types.TUINT32}:  ssa.OpRsh64x32,
2576	{ir.ORSH, types.TUINT64, types.TUINT32}: ssa.OpRsh64Ux32,
2577	{ir.ORSH, types.TINT64, types.TUINT64}:  ssa.OpRsh64x64,
2578	{ir.ORSH, types.TUINT64, types.TUINT64}: ssa.OpRsh64Ux64,
2579}
2580
2581func (s *state) ssaShiftOp(op ir.Op, t *types.Type, u *types.Type) ssa.Op {
2582	etype1 := s.concreteEtype(t)
2583	etype2 := s.concreteEtype(u)
2584	x, ok := shiftOpToSSA[opAndTwoTypes{op, etype1, etype2}]
2585	if !ok {
2586		s.Fatalf("unhandled shift op %v etype=%s/%s", op, etype1, etype2)
2587	}
2588	return x
2589}
2590
2591func (s *state) uintptrConstant(v uint64) *ssa.Value {
2592	if s.config.PtrSize == 4 {
2593		return s.newValue0I(ssa.OpConst32, types.Types[types.TUINTPTR], int64(v))
2594	}
2595	return s.newValue0I(ssa.OpConst64, types.Types[types.TUINTPTR], int64(v))
2596}
2597
2598func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value {
2599	if ft.IsBoolean() && tt.IsKind(types.TUINT8) {
2600		// Bool -> uint8 is generated internally when indexing into runtime.staticbyte.
2601		return s.newValue1(ssa.OpCvtBoolToUint8, tt, v)
2602	}
2603	if ft.IsInteger() && tt.IsInteger() {
2604		var op ssa.Op
2605		if tt.Size() == ft.Size() {
2606			op = ssa.OpCopy
2607		} else if tt.Size() < ft.Size() {
2608			// truncation
2609			switch 10*ft.Size() + tt.Size() {
2610			case 21:
2611				op = ssa.OpTrunc16to8
2612			case 41:
2613				op = ssa.OpTrunc32to8
2614			case 42:
2615				op = ssa.OpTrunc32to16
2616			case 81:
2617				op = ssa.OpTrunc64to8
2618			case 82:
2619				op = ssa.OpTrunc64to16
2620			case 84:
2621				op = ssa.OpTrunc64to32
2622			default:
2623				s.Fatalf("weird integer truncation %v -> %v", ft, tt)
2624			}
2625		} else if ft.IsSigned() {
2626			// sign extension
2627			switch 10*ft.Size() + tt.Size() {
2628			case 12:
2629				op = ssa.OpSignExt8to16
2630			case 14:
2631				op = ssa.OpSignExt8to32
2632			case 18:
2633				op = ssa.OpSignExt8to64
2634			case 24:
2635				op = ssa.OpSignExt16to32
2636			case 28:
2637				op = ssa.OpSignExt16to64
2638			case 48:
2639				op = ssa.OpSignExt32to64
2640			default:
2641				s.Fatalf("bad integer sign extension %v -> %v", ft, tt)
2642			}
2643		} else {
2644			// zero extension
2645			switch 10*ft.Size() + tt.Size() {
2646			case 12:
2647				op = ssa.OpZeroExt8to16
2648			case 14:
2649				op = ssa.OpZeroExt8to32
2650			case 18:
2651				op = ssa.OpZeroExt8to64
2652			case 24:
2653				op = ssa.OpZeroExt16to32
2654			case 28:
2655				op = ssa.OpZeroExt16to64
2656			case 48:
2657				op = ssa.OpZeroExt32to64
2658			default:
2659				s.Fatalf("weird integer sign extension %v -> %v", ft, tt)
2660			}
2661		}
2662		return s.newValue1(op, tt, v)
2663	}
2664
2665	if ft.IsComplex() && tt.IsComplex() {
2666		var op ssa.Op
2667		if ft.Size() == tt.Size() {
2668			switch ft.Size() {
2669			case 8:
2670				op = ssa.OpRound32F
2671			case 16:
2672				op = ssa.OpRound64F
2673			default:
2674				s.Fatalf("weird complex conversion %v -> %v", ft, tt)
2675			}
2676		} else if ft.Size() == 8 && tt.Size() == 16 {
2677			op = ssa.OpCvt32Fto64F
2678		} else if ft.Size() == 16 && tt.Size() == 8 {
2679			op = ssa.OpCvt64Fto32F
2680		} else {
2681			s.Fatalf("weird complex conversion %v -> %v", ft, tt)
2682		}
2683		ftp := types.FloatForComplex(ft)
2684		ttp := types.FloatForComplex(tt)
2685		return s.newValue2(ssa.OpComplexMake, tt,
2686			s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)),
2687			s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v)))
2688	}
2689
2690	if tt.IsComplex() { // and ft is not complex
2691		// Needed for generics support - can't happen in normal Go code.
2692		et := types.FloatForComplex(tt)
2693		v = s.conv(n, v, ft, et)
2694		return s.newValue2(ssa.OpComplexMake, tt, v, s.zeroVal(et))
2695	}
2696
2697	if ft.IsFloat() || tt.IsFloat() {
2698		conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
2699		if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat {
2700			if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
2701				conv = conv1
2702			}
2703		}
2704		if Arch.LinkArch.Family == sys.ARM64 || Arch.LinkArch.Family == sys.Wasm || Arch.LinkArch.Family == sys.S390X || s.softFloat {
2705			if conv1, ok1 := uint64fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
2706				conv = conv1
2707			}
2708		}
2709
2710		if Arch.LinkArch.Family == sys.MIPS && !s.softFloat {
2711			if ft.Size() == 4 && ft.IsInteger() && !ft.IsSigned() {
2712				// tt is float32 or float64, and ft is also unsigned
2713				if tt.Size() == 4 {
2714					return s.uint32Tofloat32(n, v, ft, tt)
2715				}
2716				if tt.Size() == 8 {
2717					return s.uint32Tofloat64(n, v, ft, tt)
2718				}
2719			} else if tt.Size() == 4 && tt.IsInteger() && !tt.IsSigned() {
2720				// ft is float32 or float64, and tt is unsigned integer
2721				if ft.Size() == 4 {
2722					return s.float32ToUint32(n, v, ft, tt)
2723				}
2724				if ft.Size() == 8 {
2725					return s.float64ToUint32(n, v, ft, tt)
2726				}
2727			}
2728		}
2729
2730		if !ok {
2731			s.Fatalf("weird float conversion %v -> %v", ft, tt)
2732		}
2733		op1, op2, it := conv.op1, conv.op2, conv.intermediateType
2734
2735		if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid {
2736			// normal case, not tripping over unsigned 64
2737			if op1 == ssa.OpCopy {
2738				if op2 == ssa.OpCopy {
2739					return v
2740				}
2741				return s.newValueOrSfCall1(op2, tt, v)
2742			}
2743			if op2 == ssa.OpCopy {
2744				return s.newValueOrSfCall1(op1, tt, v)
2745			}
2746			return s.newValueOrSfCall1(op2, tt, s.newValueOrSfCall1(op1, types.Types[it], v))
2747		}
2748		// Tricky 64-bit unsigned cases.
2749		if ft.IsInteger() {
2750			// tt is float32 or float64, and ft is also unsigned
2751			if tt.Size() == 4 {
2752				return s.uint64Tofloat32(n, v, ft, tt)
2753			}
2754			if tt.Size() == 8 {
2755				return s.uint64Tofloat64(n, v, ft, tt)
2756			}
2757			s.Fatalf("weird unsigned integer to float conversion %v -> %v", ft, tt)
2758		}
2759		// ft is float32 or float64, and tt is unsigned integer
2760		if ft.Size() == 4 {
2761			return s.float32ToUint64(n, v, ft, tt)
2762		}
2763		if ft.Size() == 8 {
2764			return s.float64ToUint64(n, v, ft, tt)
2765		}
2766		s.Fatalf("weird float to unsigned integer conversion %v -> %v", ft, tt)
2767		return nil
2768	}
2769
2770	s.Fatalf("unhandled OCONV %s -> %s", ft.Kind(), tt.Kind())
2771	return nil
2772}
2773
2774// expr converts the expression n to ssa, adds it to s and returns the ssa result.
2775func (s *state) expr(n ir.Node) *ssa.Value {
2776	return s.exprCheckPtr(n, true)
2777}
2778
2779func (s *state) exprCheckPtr(n ir.Node, checkPtrOK bool) *ssa.Value {
2780	if ir.HasUniquePos(n) {
2781		// ONAMEs and named OLITERALs have the line number
2782		// of the decl, not the use. See issue 14742.
2783		s.pushLine(n.Pos())
2784		defer s.popLine()
2785	}
2786
2787	s.stmtList(n.Init())
2788	switch n.Op() {
2789	case ir.OBYTES2STRTMP:
2790		n := n.(*ir.ConvExpr)
2791		slice := s.expr(n.X)
2792		ptr := s.newValue1(ssa.OpSlicePtr, s.f.Config.Types.BytePtr, slice)
2793		len := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], slice)
2794		return s.newValue2(ssa.OpStringMake, n.Type(), ptr, len)
2795	case ir.OSTR2BYTESTMP:
2796		n := n.(*ir.ConvExpr)
2797		str := s.expr(n.X)
2798		ptr := s.newValue1(ssa.OpStringPtr, s.f.Config.Types.BytePtr, str)
2799		if !n.NonNil() {
2800			// We need to ensure []byte("") evaluates to []byte{}, and not []byte(nil).
2801			//
2802			// TODO(mdempsky): Investigate using "len != 0" instead of "ptr != nil".
2803			cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], ptr, s.constNil(ptr.Type))
2804			zerobase := s.newValue1A(ssa.OpAddr, ptr.Type, ir.Syms.Zerobase, s.sb)
2805			ptr = s.ternary(cond, ptr, zerobase)
2806		}
2807		len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], str)
2808		return s.newValue3(ssa.OpSliceMake, n.Type(), ptr, len, len)
2809	case ir.OCFUNC:
2810		n := n.(*ir.UnaryExpr)
2811		aux := n.X.(*ir.Name).Linksym()
2812		// OCFUNC is used to build function values, which must
2813		// always reference ABIInternal entry points.
2814		if aux.ABI() != obj.ABIInternal {
2815			s.Fatalf("expected ABIInternal: %v", aux.ABI())
2816		}
2817		return s.entryNewValue1A(ssa.OpAddr, n.Type(), aux, s.sb)
2818	case ir.ONAME:
2819		n := n.(*ir.Name)
2820		if n.Class == ir.PFUNC {
2821			// "value" of a function is the address of the function's closure
2822			sym := staticdata.FuncLinksym(n)
2823			return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(n.Type()), sym, s.sb)
2824		}
2825		if s.canSSA(n) {
2826			return s.variable(n, n.Type())
2827		}
2828		return s.load(n.Type(), s.addr(n))
2829	case ir.OLINKSYMOFFSET:
2830		n := n.(*ir.LinksymOffsetExpr)
2831		return s.load(n.Type(), s.addr(n))
2832	case ir.ONIL:
2833		n := n.(*ir.NilExpr)
2834		t := n.Type()
2835		switch {
2836		case t.IsSlice():
2837			return s.constSlice(t)
2838		case t.IsInterface():
2839			return s.constInterface(t)
2840		default:
2841			return s.constNil(t)
2842		}
2843	case ir.OLITERAL:
2844		switch u := n.Val(); u.Kind() {
2845		case constant.Int:
2846			i := ir.IntVal(n.Type(), u)
2847			switch n.Type().Size() {
2848			case 1:
2849				return s.constInt8(n.Type(), int8(i))
2850			case 2:
2851				return s.constInt16(n.Type(), int16(i))
2852			case 4:
2853				return s.constInt32(n.Type(), int32(i))
2854			case 8:
2855				return s.constInt64(n.Type(), i)
2856			default:
2857				s.Fatalf("bad integer size %d", n.Type().Size())
2858				return nil
2859			}
2860		case constant.String:
2861			i := constant.StringVal(u)
2862			if i == "" {
2863				return s.constEmptyString(n.Type())
2864			}
2865			return s.entryNewValue0A(ssa.OpConstString, n.Type(), ssa.StringToAux(i))
2866		case constant.Bool:
2867			return s.constBool(constant.BoolVal(u))
2868		case constant.Float:
2869			f, _ := constant.Float64Val(u)
2870			switch n.Type().Size() {
2871			case 4:
2872				return s.constFloat32(n.Type(), f)
2873			case 8:
2874				return s.constFloat64(n.Type(), f)
2875			default:
2876				s.Fatalf("bad float size %d", n.Type().Size())
2877				return nil
2878			}
2879		case constant.Complex:
2880			re, _ := constant.Float64Val(constant.Real(u))
2881			im, _ := constant.Float64Val(constant.Imag(u))
2882			switch n.Type().Size() {
2883			case 8:
2884				pt := types.Types[types.TFLOAT32]
2885				return s.newValue2(ssa.OpComplexMake, n.Type(),
2886					s.constFloat32(pt, re),
2887					s.constFloat32(pt, im))
2888			case 16:
2889				pt := types.Types[types.TFLOAT64]
2890				return s.newValue2(ssa.OpComplexMake, n.Type(),
2891					s.constFloat64(pt, re),
2892					s.constFloat64(pt, im))
2893			default:
2894				s.Fatalf("bad complex size %d", n.Type().Size())
2895				return nil
2896			}
2897		default:
2898			s.Fatalf("unhandled OLITERAL %v", u.Kind())
2899			return nil
2900		}
2901	case ir.OCONVNOP:
2902		n := n.(*ir.ConvExpr)
2903		to := n.Type()
2904		from := n.X.Type()
2905
2906		// Assume everything will work out, so set up our return value.
2907		// Anything interesting that happens from here is a fatal.
2908		x := s.expr(n.X)
2909		if to == from {
2910			return x
2911		}
2912
2913		// Special case for not confusing GC and liveness.
2914		// We don't want pointers accidentally classified
2915		// as not-pointers or vice-versa because of copy
2916		// elision.
2917		if to.IsPtrShaped() != from.IsPtrShaped() {
2918			return s.newValue2(ssa.OpConvert, to, x, s.mem())
2919		}
2920
2921		v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type
2922
2923		// CONVNOP closure
2924		if to.Kind() == types.TFUNC && from.IsPtrShaped() {
2925			return v
2926		}
2927
2928		// named <--> unnamed type or typed <--> untyped const
2929		if from.Kind() == to.Kind() {
2930			return v
2931		}
2932
2933		// unsafe.Pointer <--> *T
2934		if to.IsUnsafePtr() && from.IsPtrShaped() || from.IsUnsafePtr() && to.IsPtrShaped() {
2935			if s.checkPtrEnabled && checkPtrOK && to.IsPtr() && from.IsUnsafePtr() {
2936				s.checkPtrAlignment(n, v, nil)
2937			}
2938			return v
2939		}
2940
2941		// map <--> *hmap
2942		if to.Kind() == types.TMAP && from == types.NewPtr(reflectdata.MapType()) {
2943			return v
2944		}
2945
2946		types.CalcSize(from)
2947		types.CalcSize(to)
2948		if from.Size() != to.Size() {
2949			s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Size(), to, to.Size())
2950			return nil
2951		}
2952		if etypesign(from.Kind()) != etypesign(to.Kind()) {
2953			s.Fatalf("CONVNOP sign mismatch %v (%s) -> %v (%s)\n", from, from.Kind(), to, to.Kind())
2954			return nil
2955		}
2956
2957		if base.Flag.Cfg.Instrumenting {
2958			// These appear to be fine, but they fail the
2959			// integer constraint below, so okay them here.
2960			// Sample non-integer conversion: map[string]string -> *uint8
2961			return v
2962		}
2963
2964		if etypesign(from.Kind()) == 0 {
2965			s.Fatalf("CONVNOP unrecognized non-integer %v -> %v\n", from, to)
2966			return nil
2967		}
2968
2969		// integer, same width, same sign
2970		return v
2971
2972	case ir.OCONV:
2973		n := n.(*ir.ConvExpr)
2974		x := s.expr(n.X)
2975		return s.conv(n, x, n.X.Type(), n.Type())
2976
2977	case ir.ODOTTYPE:
2978		n := n.(*ir.TypeAssertExpr)
2979		res, _ := s.dottype(n, false)
2980		return res
2981
2982	case ir.ODYNAMICDOTTYPE:
2983		n := n.(*ir.DynamicTypeAssertExpr)
2984		res, _ := s.dynamicDottype(n, false)
2985		return res
2986
2987	// binary ops
2988	case ir.OLT, ir.OEQ, ir.ONE, ir.OLE, ir.OGE, ir.OGT:
2989		n := n.(*ir.BinaryExpr)
2990		a := s.expr(n.X)
2991		b := s.expr(n.Y)
2992		if n.X.Type().IsComplex() {
2993			pt := types.FloatForComplex(n.X.Type())
2994			op := s.ssaOp(ir.OEQ, pt)
2995			r := s.newValueOrSfCall2(op, types.Types[types.TBOOL], s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b))
2996			i := s.newValueOrSfCall2(op, types.Types[types.TBOOL], s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b))
2997			c := s.newValue2(ssa.OpAndB, types.Types[types.TBOOL], r, i)
2998			switch n.Op() {
2999			case ir.OEQ:
3000				return c
3001			case ir.ONE:
3002				return s.newValue1(ssa.OpNot, types.Types[types.TBOOL], c)
3003			default:
3004				s.Fatalf("ordered complex compare %v", n.Op())
3005			}
3006		}
3007
3008		// Convert OGE and OGT into OLE and OLT.
3009		op := n.Op()
3010		switch op {
3011		case ir.OGE:
3012			op, a, b = ir.OLE, b, a
3013		case ir.OGT:
3014			op, a, b = ir.OLT, b, a
3015		}
3016		if n.X.Type().IsFloat() {
3017			// float comparison
3018			return s.newValueOrSfCall2(s.ssaOp(op, n.X.Type()), types.Types[types.TBOOL], a, b)
3019		}
3020		// integer comparison
3021		return s.newValue2(s.ssaOp(op, n.X.Type()), types.Types[types.TBOOL], a, b)
3022	case ir.OMUL:
3023		n := n.(*ir.BinaryExpr)
3024		a := s.expr(n.X)
3025		b := s.expr(n.Y)
3026		if n.Type().IsComplex() {
3027			mulop := ssa.OpMul64F
3028			addop := ssa.OpAdd64F
3029			subop := ssa.OpSub64F
3030			pt := types.FloatForComplex(n.Type()) // Could be Float32 or Float64
3031			wt := types.Types[types.TFLOAT64]     // Compute in Float64 to minimize cancellation error
3032
3033			areal := s.newValue1(ssa.OpComplexReal, pt, a)
3034			breal := s.newValue1(ssa.OpComplexReal, pt, b)
3035			aimag := s.newValue1(ssa.OpComplexImag, pt, a)
3036			bimag := s.newValue1(ssa.OpComplexImag, pt, b)
3037
3038			if pt != wt { // Widen for calculation
3039				areal = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, areal)
3040				breal = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, breal)
3041				aimag = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, aimag)
3042				bimag = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, bimag)
3043			}
3044
3045			xreal := s.newValueOrSfCall2(subop, wt, s.newValueOrSfCall2(mulop, wt, areal, breal), s.newValueOrSfCall2(mulop, wt, aimag, bimag))
3046			ximag := s.newValueOrSfCall2(addop, wt, s.newValueOrSfCall2(mulop, wt, areal, bimag), s.newValueOrSfCall2(mulop, wt, aimag, breal))
3047
3048			if pt != wt { // Narrow to store back
3049				xreal = s.newValueOrSfCall1(ssa.OpCvt64Fto32F, pt, xreal)
3050				ximag = s.newValueOrSfCall1(ssa.OpCvt64Fto32F, pt, ximag)
3051			}
3052
3053			return s.newValue2(ssa.OpComplexMake, n.Type(), xreal, ximag)
3054		}
3055
3056		if n.Type().IsFloat() {
3057			return s.newValueOrSfCall2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3058		}
3059
3060		return s.newValue2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3061
3062	case ir.ODIV:
3063		n := n.(*ir.BinaryExpr)
3064		a := s.expr(n.X)
3065		b := s.expr(n.Y)
3066		if n.Type().IsComplex() {
3067			// TODO this is not executed because the front-end substitutes a runtime call.
3068			// That probably ought to change; with modest optimization the widen/narrow
3069			// conversions could all be elided in larger expression trees.
3070			mulop := ssa.OpMul64F
3071			addop := ssa.OpAdd64F
3072			subop := ssa.OpSub64F
3073			divop := ssa.OpDiv64F
3074			pt := types.FloatForComplex(n.Type()) // Could be Float32 or Float64
3075			wt := types.Types[types.TFLOAT64]     // Compute in Float64 to minimize cancellation error
3076
3077			areal := s.newValue1(ssa.OpComplexReal, pt, a)
3078			breal := s.newValue1(ssa.OpComplexReal, pt, b)
3079			aimag := s.newValue1(ssa.OpComplexImag, pt, a)
3080			bimag := s.newValue1(ssa.OpComplexImag, pt, b)
3081
3082			if pt != wt { // Widen for calculation
3083				areal = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, areal)
3084				breal = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, breal)
3085				aimag = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, aimag)
3086				bimag = s.newValueOrSfCall1(ssa.OpCvt32Fto64F, wt, bimag)
3087			}
3088
3089			denom := s.newValueOrSfCall2(addop, wt, s.newValueOrSfCall2(mulop, wt, breal, breal), s.newValueOrSfCall2(mulop, wt, bimag, bimag))
3090			xreal := s.newValueOrSfCall2(addop, wt, s.newValueOrSfCall2(mulop, wt, areal, breal), s.newValueOrSfCall2(mulop, wt, aimag, bimag))
3091			ximag := s.newValueOrSfCall2(subop, wt, s.newValueOrSfCall2(mulop, wt, aimag, breal), s.newValueOrSfCall2(mulop, wt, areal, bimag))
3092
3093			// TODO not sure if this is best done in wide precision or narrow
3094			// Double-rounding might be an issue.
3095			// Note that the pre-SSA implementation does the entire calculation
3096			// in wide format, so wide is compatible.
3097			xreal = s.newValueOrSfCall2(divop, wt, xreal, denom)
3098			ximag = s.newValueOrSfCall2(divop, wt, ximag, denom)
3099
3100			if pt != wt { // Narrow to store back
3101				xreal = s.newValueOrSfCall1(ssa.OpCvt64Fto32F, pt, xreal)
3102				ximag = s.newValueOrSfCall1(ssa.OpCvt64Fto32F, pt, ximag)
3103			}
3104			return s.newValue2(ssa.OpComplexMake, n.Type(), xreal, ximag)
3105		}
3106		if n.Type().IsFloat() {
3107			return s.newValueOrSfCall2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3108		}
3109		return s.intDivide(n, a, b)
3110	case ir.OMOD:
3111		n := n.(*ir.BinaryExpr)
3112		a := s.expr(n.X)
3113		b := s.expr(n.Y)
3114		return s.intDivide(n, a, b)
3115	case ir.OADD, ir.OSUB:
3116		n := n.(*ir.BinaryExpr)
3117		a := s.expr(n.X)
3118		b := s.expr(n.Y)
3119		if n.Type().IsComplex() {
3120			pt := types.FloatForComplex(n.Type())
3121			op := s.ssaOp(n.Op(), pt)
3122			return s.newValue2(ssa.OpComplexMake, n.Type(),
3123				s.newValueOrSfCall2(op, pt, s.newValue1(ssa.OpComplexReal, pt, a), s.newValue1(ssa.OpComplexReal, pt, b)),
3124				s.newValueOrSfCall2(op, pt, s.newValue1(ssa.OpComplexImag, pt, a), s.newValue1(ssa.OpComplexImag, pt, b)))
3125		}
3126		if n.Type().IsFloat() {
3127			return s.newValueOrSfCall2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3128		}
3129		return s.newValue2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3130	case ir.OAND, ir.OOR, ir.OXOR:
3131		n := n.(*ir.BinaryExpr)
3132		a := s.expr(n.X)
3133		b := s.expr(n.Y)
3134		return s.newValue2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
3135	case ir.OANDNOT:
3136		n := n.(*ir.BinaryExpr)
3137		a := s.expr(n.X)
3138		b := s.expr(n.Y)
3139		b = s.newValue1(s.ssaOp(ir.OBITNOT, b.Type), b.Type, b)
3140		return s.newValue2(s.ssaOp(ir.OAND, n.Type()), a.Type, a, b)
3141	case ir.OLSH, ir.ORSH:
3142		n := n.(*ir.BinaryExpr)
3143		a := s.expr(n.X)
3144		b := s.expr(n.Y)
3145		bt := b.Type
3146		if bt.IsSigned() {
3147			cmp := s.newValue2(s.ssaOp(ir.OLE, bt), types.Types[types.TBOOL], s.zeroVal(bt), b)
3148			s.check(cmp, ir.Syms.Panicshift)
3149			bt = bt.ToUnsigned()
3150		}
3151		return s.newValue2(s.ssaShiftOp(n.Op(), n.Type(), bt), a.Type, a, b)
3152	case ir.OANDAND, ir.OOROR:
3153		// To implement OANDAND (and OOROR), we introduce a
3154		// new temporary variable to hold the result. The
3155		// variable is associated with the OANDAND node in the
3156		// s.vars table (normally variables are only
3157		// associated with ONAME nodes). We convert
3158		//     A && B
3159		// to
3160		//     var = A
3161		//     if var {
3162		//         var = B
3163		//     }
3164		// Using var in the subsequent block introduces the
3165		// necessary phi variable.
3166		n := n.(*ir.LogicalExpr)
3167		el := s.expr(n.X)
3168		s.vars[n] = el
3169
3170		b := s.endBlock()
3171		b.Kind = ssa.BlockIf
3172		b.SetControl(el)
3173		// In theory, we should set b.Likely here based on context.
3174		// However, gc only gives us likeliness hints
3175		// in a single place, for plain OIF statements,
3176		// and passing around context is finicky, so don't bother for now.
3177
3178		bRight := s.f.NewBlock(ssa.BlockPlain)
3179		bResult := s.f.NewBlock(ssa.BlockPlain)
3180		if n.Op() == ir.OANDAND {
3181			b.AddEdgeTo(bRight)
3182			b.AddEdgeTo(bResult)
3183		} else if n.Op() == ir.OOROR {
3184			b.AddEdgeTo(bResult)
3185			b.AddEdgeTo(bRight)
3186		}
3187
3188		s.startBlock(bRight)
3189		er := s.expr(n.Y)
3190		s.vars[n] = er
3191
3192		b = s.endBlock()
3193		b.AddEdgeTo(bResult)
3194
3195		s.startBlock(bResult)
3196		return s.variable(n, types.Types[types.TBOOL])
3197	case ir.OCOMPLEX:
3198		n := n.(*ir.BinaryExpr)
3199		r := s.expr(n.X)
3200		i := s.expr(n.Y)
3201		return s.newValue2(ssa.OpComplexMake, n.Type(), r, i)
3202
3203	// unary ops
3204	case ir.ONEG:
3205		n := n.(*ir.UnaryExpr)
3206		a := s.expr(n.X)
3207		if n.Type().IsComplex() {
3208			tp := types.FloatForComplex(n.Type())
3209			negop := s.ssaOp(n.Op(), tp)
3210			return s.newValue2(ssa.OpComplexMake, n.Type(),
3211				s.newValue1(negop, tp, s.newValue1(ssa.OpComplexReal, tp, a)),
3212				s.newValue1(negop, tp, s.newValue1(ssa.OpComplexImag, tp, a)))
3213		}
3214		return s.newValue1(s.ssaOp(n.Op(), n.Type()), a.Type, a)
3215	case ir.ONOT, ir.OBITNOT:
3216		n := n.(*ir.UnaryExpr)
3217		a := s.expr(n.X)
3218		return s.newValue1(s.ssaOp(n.Op(), n.Type()), a.Type, a)
3219	case ir.OIMAG, ir.OREAL:
3220		n := n.(*ir.UnaryExpr)
3221		a := s.expr(n.X)
3222		return s.newValue1(s.ssaOp(n.Op(), n.X.Type()), n.Type(), a)
3223	case ir.OPLUS:
3224		n := n.(*ir.UnaryExpr)
3225		return s.expr(n.X)
3226
3227	case ir.OADDR:
3228		n := n.(*ir.AddrExpr)
3229		return s.addr(n.X)
3230
3231	case ir.ORESULT:
3232		n := n.(*ir.ResultExpr)
3233		if s.prevCall == nil || s.prevCall.Op != ssa.OpStaticLECall && s.prevCall.Op != ssa.OpInterLECall && s.prevCall.Op != ssa.OpClosureLECall {
3234			panic("Expected to see a previous call")
3235		}
3236		which := n.Index
3237		if which == -1 {
3238			panic(fmt.Errorf("ORESULT %v does not match call %s", n, s.prevCall))
3239		}
3240		return s.resultOfCall(s.prevCall, which, n.Type())
3241
3242	case ir.ODEREF:
3243		n := n.(*ir.StarExpr)
3244		p := s.exprPtr(n.X, n.Bounded(), n.Pos())
3245		return s.load(n.Type(), p)
3246
3247	case ir.ODOT:
3248		n := n.(*ir.SelectorExpr)
3249		if n.X.Op() == ir.OSTRUCTLIT {
3250			// All literals with nonzero fields have already been
3251			// rewritten during walk. Any that remain are just T{}
3252			// or equivalents. Use the zero value.
3253			if !ir.IsZero(n.X) {
3254				s.Fatalf("literal with nonzero value in SSA: %v", n.X)
3255			}
3256			return s.zeroVal(n.Type())
3257		}
3258		// If n is addressable and can't be represented in
3259		// SSA, then load just the selected field. This
3260		// prevents false memory dependencies in race/msan/asan
3261		// instrumentation.
3262		if ir.IsAddressable(n) && !s.canSSA(n) {
3263			p := s.addr(n)
3264			return s.load(n.Type(), p)
3265		}
3266		v := s.expr(n.X)
3267		return s.newValue1I(ssa.OpStructSelect, n.Type(), int64(fieldIdx(n)), v)
3268
3269	case ir.ODOTPTR:
3270		n := n.(*ir.SelectorExpr)
3271		p := s.exprPtr(n.X, n.Bounded(), n.Pos())
3272		p = s.newValue1I(ssa.OpOffPtr, types.NewPtr(n.Type()), n.Offset(), p)
3273		return s.load(n.Type(), p)
3274
3275	case ir.OINDEX:
3276		n := n.(*ir.IndexExpr)
3277		switch {
3278		case n.X.Type().IsString():
3279			if n.Bounded() && ir.IsConst(n.X, constant.String) && ir.IsConst(n.Index, constant.Int) {
3280				// Replace "abc"[1] with 'b'.
3281				// Delayed until now because "abc"[1] is not an ideal constant.
3282				// See test/fixedbugs/issue11370.go.
3283				return s.newValue0I(ssa.OpConst8, types.Types[types.TUINT8], int64(int8(ir.StringVal(n.X)[ir.Int64Val(n.Index)])))
3284			}
3285			a := s.expr(n.X)
3286			i := s.expr(n.Index)
3287			len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], a)
3288			i = s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded())
3289			ptrtyp := s.f.Config.Types.BytePtr
3290			ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
3291			if ir.IsConst(n.Index, constant.Int) {
3292				ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, ir.Int64Val(n.Index), ptr)
3293			} else {
3294				ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
3295			}
3296			return s.load(types.Types[types.TUINT8], ptr)
3297		case n.X.Type().IsSlice():
3298			p := s.addr(n)
3299			return s.load(n.X.Type().Elem(), p)
3300		case n.X.Type().IsArray():
3301			if ssa.CanSSA(n.X.Type()) {
3302				// SSA can handle arrays of length at most 1.
3303				bound := n.X.Type().NumElem()
3304				a := s.expr(n.X)
3305				i := s.expr(n.Index)
3306				if bound == 0 {
3307					// Bounds check will never succeed.  Might as well
3308					// use constants for the bounds check.
3309					z := s.constInt(types.Types[types.TINT], 0)
3310					s.boundsCheck(z, z, ssa.BoundsIndex, false)
3311					// The return value won't be live, return junk.
3312					// But not quite junk, in case bounds checks are turned off. See issue 48092.
3313					return s.zeroVal(n.Type())
3314				}
3315				len := s.constInt(types.Types[types.TINT], bound)
3316				s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded()) // checks i == 0
3317				return s.newValue1I(ssa.OpArraySelect, n.Type(), 0, a)
3318			}
3319			p := s.addr(n)
3320			return s.load(n.X.Type().Elem(), p)
3321		default:
3322			s.Fatalf("bad type for index %v", n.X.Type())
3323			return nil
3324		}
3325
3326	case ir.OLEN, ir.OCAP:
3327		n := n.(*ir.UnaryExpr)
3328		switch {
3329		case n.X.Type().IsSlice():
3330			op := ssa.OpSliceLen
3331			if n.Op() == ir.OCAP {
3332				op = ssa.OpSliceCap
3333			}
3334			return s.newValue1(op, types.Types[types.TINT], s.expr(n.X))
3335		case n.X.Type().IsString(): // string; not reachable for OCAP
3336			return s.newValue1(ssa.OpStringLen, types.Types[types.TINT], s.expr(n.X))
3337		case n.X.Type().IsMap(), n.X.Type().IsChan():
3338			return s.referenceTypeBuiltin(n, s.expr(n.X))
3339		default: // array
3340			return s.constInt(types.Types[types.TINT], n.X.Type().NumElem())
3341		}
3342
3343	case ir.OSPTR:
3344		n := n.(*ir.UnaryExpr)
3345		a := s.expr(n.X)
3346		if n.X.Type().IsSlice() {
3347			if n.Bounded() {
3348				return s.newValue1(ssa.OpSlicePtr, n.Type(), a)
3349			}
3350			return s.newValue1(ssa.OpSlicePtrUnchecked, n.Type(), a)
3351		} else {
3352			return s.newValue1(ssa.OpStringPtr, n.Type(), a)
3353		}
3354
3355	case ir.OITAB:
3356		n := n.(*ir.UnaryExpr)
3357		a := s.expr(n.X)
3358		return s.newValue1(ssa.OpITab, n.Type(), a)
3359
3360	case ir.OIDATA:
3361		n := n.(*ir.UnaryExpr)
3362		a := s.expr(n.X)
3363		return s.newValue1(ssa.OpIData, n.Type(), a)
3364
3365	case ir.OMAKEFACE:
3366		n := n.(*ir.BinaryExpr)
3367		tab := s.expr(n.X)
3368		data := s.expr(n.Y)
3369		return s.newValue2(ssa.OpIMake, n.Type(), tab, data)
3370
3371	case ir.OSLICEHEADER:
3372		n := n.(*ir.SliceHeaderExpr)
3373		p := s.expr(n.Ptr)
3374		l := s.expr(n.Len)
3375		c := s.expr(n.Cap)
3376		return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
3377
3378	case ir.OSTRINGHEADER:
3379		n := n.(*ir.StringHeaderExpr)
3380		p := s.expr(n.Ptr)
3381		l := s.expr(n.Len)
3382		return s.newValue2(ssa.OpStringMake, n.Type(), p, l)
3383
3384	case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR:
3385		n := n.(*ir.SliceExpr)
3386		check := s.checkPtrEnabled && n.Op() == ir.OSLICE3ARR && n.X.Op() == ir.OCONVNOP && n.X.(*ir.ConvExpr).X.Type().IsUnsafePtr()
3387		v := s.exprCheckPtr(n.X, !check)
3388		var i, j, k *ssa.Value
3389		if n.Low != nil {
3390			i = s.expr(n.Low)
3391		}
3392		if n.High != nil {
3393			j = s.expr(n.High)
3394		}
3395		if n.Max != nil {
3396			k = s.expr(n.Max)
3397		}
3398		p, l, c := s.slice(v, i, j, k, n.Bounded())
3399		if check {
3400			// Emit checkptr instrumentation after bound check to prevent false positive, see #46938.
3401			s.checkPtrAlignment(n.X.(*ir.ConvExpr), v, s.conv(n.Max, k, k.Type, types.Types[types.TUINTPTR]))
3402		}
3403		return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
3404
3405	case ir.OSLICESTR:
3406		n := n.(*ir.SliceExpr)
3407		v := s.expr(n.X)
3408		var i, j *ssa.Value
3409		if n.Low != nil {
3410			i = s.expr(n.Low)
3411		}
3412		if n.High != nil {
3413			j = s.expr(n.High)
3414		}
3415		p, l, _ := s.slice(v, i, j, nil, n.Bounded())
3416		return s.newValue2(ssa.OpStringMake, n.Type(), p, l)
3417
3418	case ir.OSLICE2ARRPTR:
3419		// if arrlen > slice.len {
3420		//   panic(...)
3421		// }
3422		// slice.ptr
3423		n := n.(*ir.ConvExpr)
3424		v := s.expr(n.X)
3425		nelem := n.Type().Elem().NumElem()
3426		arrlen := s.constInt(types.Types[types.TINT], nelem)
3427		cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v)
3428		s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false)
3429		op := ssa.OpSlicePtr
3430		if nelem == 0 {
3431			op = ssa.OpSlicePtrUnchecked
3432		}
3433		return s.newValue1(op, n.Type(), v)
3434
3435	case ir.OCALLFUNC:
3436		n := n.(*ir.CallExpr)
3437		if ir.IsIntrinsicCall(n) {
3438			return s.intrinsicCall(n)
3439		}
3440		fallthrough
3441
3442	case ir.OCALLINTER:
3443		n := n.(*ir.CallExpr)
3444		return s.callResult(n, callNormal)
3445
3446	case ir.OGETG:
3447		n := n.(*ir.CallExpr)
3448		return s.newValue1(ssa.OpGetG, n.Type(), s.mem())
3449
3450	case ir.OGETCALLERPC:
3451		n := n.(*ir.CallExpr)
3452		return s.newValue0(ssa.OpGetCallerPC, n.Type())
3453
3454	case ir.OGETCALLERSP:
3455		n := n.(*ir.CallExpr)
3456		return s.newValue1(ssa.OpGetCallerSP, n.Type(), s.mem())
3457
3458	case ir.OAPPEND:
3459		return s.append(n.(*ir.CallExpr), false)
3460
3461	case ir.OMIN, ir.OMAX:
3462		return s.minMax(n.(*ir.CallExpr))
3463
3464	case ir.OSTRUCTLIT, ir.OARRAYLIT:
3465		// All literals with nonzero fields have already been
3466		// rewritten during walk. Any that remain are just T{}
3467		// or equivalents. Use the zero value.
3468		n := n.(*ir.CompLitExpr)
3469		if !ir.IsZero(n) {
3470			s.Fatalf("literal with nonzero value in SSA: %v", n)
3471		}
3472		return s.zeroVal(n.Type())
3473
3474	case ir.ONEW:
3475		n := n.(*ir.UnaryExpr)
3476		var rtype *ssa.Value
3477		if x, ok := n.X.(*ir.DynamicType); ok && x.Op() == ir.ODYNAMICTYPE {
3478			rtype = s.expr(x.RType)
3479		}
3480		return s.newObject(n.Type().Elem(), rtype)
3481
3482	case ir.OUNSAFEADD:
3483		n := n.(*ir.BinaryExpr)
3484		ptr := s.expr(n.X)
3485		len := s.expr(n.Y)
3486
3487		// Force len to uintptr to prevent misuse of garbage bits in the
3488		// upper part of the register (#48536).
3489		len = s.conv(n, len, len.Type, types.Types[types.TUINTPTR])
3490
3491		return s.newValue2(ssa.OpAddPtr, n.Type(), ptr, len)
3492
3493	default:
3494		s.Fatalf("unhandled expr %v", n.Op())
3495		return nil
3496	}
3497}
3498
3499func (s *state) resultOfCall(c *ssa.Value, which int64, t *types.Type) *ssa.Value {
3500	aux := c.Aux.(*ssa.AuxCall)
3501	pa := aux.ParamAssignmentForResult(which)
3502	// TODO(register args) determine if in-memory TypeOK is better loaded early from SelectNAddr or later when SelectN is expanded.
3503	// SelectN is better for pattern-matching and possible call-aware analysis we might want to do in the future.
3504	if len(pa.Registers) == 0 && !ssa.CanSSA(t) {
3505		addr := s.newValue1I(ssa.OpSelectNAddr, types.NewPtr(t), which, c)
3506		return s.rawLoad(t, addr)
3507	}
3508	return s.newValue1I(ssa.OpSelectN, t, which, c)
3509}
3510
3511func (s *state) resultAddrOfCall(c *ssa.Value, which int64, t *types.Type) *ssa.Value {
3512	aux := c.Aux.(*ssa.AuxCall)
3513	pa := aux.ParamAssignmentForResult(which)
3514	if len(pa.Registers) == 0 {
3515		return s.newValue1I(ssa.OpSelectNAddr, types.NewPtr(t), which, c)
3516	}
3517	_, addr := s.temp(c.Pos, t)
3518	rval := s.newValue1I(ssa.OpSelectN, t, which, c)
3519	s.vars[memVar] = s.newValue3Apos(ssa.OpStore, types.TypeMem, t, addr, rval, s.mem(), false)
3520	return addr
3521}
3522
3523// append converts an OAPPEND node to SSA.
3524// If inplace is false, it converts the OAPPEND expression n to an ssa.Value,
3525// adds it to s, and returns the Value.
3526// If inplace is true, it writes the result of the OAPPEND expression n
3527// back to the slice being appended to, and returns nil.
3528// inplace MUST be set to false if the slice can be SSA'd.
3529// Note: this code only handles fixed-count appends. Dotdotdot appends
3530// have already been rewritten at this point (by walk).
3531func (s *state) append(n *ir.CallExpr, inplace bool) *ssa.Value {
3532	// If inplace is false, process as expression "append(s, e1, e2, e3)":
3533	//
3534	// ptr, len, cap := s
3535	// len += 3
3536	// if uint(len) > uint(cap) {
3537	//     ptr, len, cap = growslice(ptr, len, cap, 3, typ)
3538	//     Note that len is unmodified by growslice.
3539	// }
3540	// // with write barriers, if needed:
3541	// *(ptr+(len-3)) = e1
3542	// *(ptr+(len-2)) = e2
3543	// *(ptr+(len-1)) = e3
3544	// return makeslice(ptr, len, cap)
3545	//
3546	//
3547	// If inplace is true, process as statement "s = append(s, e1, e2, e3)":
3548	//
3549	// a := &s
3550	// ptr, len, cap := s
3551	// len += 3
3552	// if uint(len) > uint(cap) {
3553	//    ptr, len, cap = growslice(ptr, len, cap, 3, typ)
3554	//    vardef(a)    // if necessary, advise liveness we are writing a new a
3555	//    *a.cap = cap // write before ptr to avoid a spill
3556	//    *a.ptr = ptr // with write barrier
3557	// }
3558	// *a.len = len
3559	// // with write barriers, if needed:
3560	// *(ptr+(len-3)) = e1
3561	// *(ptr+(len-2)) = e2
3562	// *(ptr+(len-1)) = e3
3563
3564	et := n.Type().Elem()
3565	pt := types.NewPtr(et)
3566
3567	// Evaluate slice
3568	sn := n.Args[0] // the slice node is the first in the list
3569	var slice, addr *ssa.Value
3570	if inplace {
3571		addr = s.addr(sn)
3572		slice = s.load(n.Type(), addr)
3573	} else {
3574		slice = s.expr(sn)
3575	}
3576
3577	// Allocate new blocks
3578	grow := s.f.NewBlock(ssa.BlockPlain)
3579	assign := s.f.NewBlock(ssa.BlockPlain)
3580
3581	// Decomposse input slice.
3582	p := s.newValue1(ssa.OpSlicePtr, pt, slice)
3583	l := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], slice)
3584	c := s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], slice)
3585
3586	// Add number of new elements to length.
3587	nargs := s.constInt(types.Types[types.TINT], int64(len(n.Args)-1))
3588	l = s.newValue2(s.ssaOp(ir.OADD, types.Types[types.TINT]), types.Types[types.TINT], l, nargs)
3589
3590	// Decide if we need to grow
3591	cmp := s.newValue2(s.ssaOp(ir.OLT, types.Types[types.TUINT]), types.Types[types.TBOOL], c, l)
3592
3593	// Record values of ptr/len/cap before branch.
3594	s.vars[ptrVar] = p
3595	s.vars[lenVar] = l
3596	if !inplace {
3597		s.vars[capVar] = c
3598	}
3599
3600	b := s.endBlock()
3601	b.Kind = ssa.BlockIf
3602	b.Likely = ssa.BranchUnlikely
3603	b.SetControl(cmp)
3604	b.AddEdgeTo(grow)
3605	b.AddEdgeTo(assign)
3606
3607	// Call growslice
3608	s.startBlock(grow)
3609	taddr := s.expr(n.Fun)
3610	r := s.rtcall(ir.Syms.Growslice, true, []*types.Type{n.Type()}, p, l, c, nargs, taddr)
3611
3612	// Decompose output slice
3613	p = s.newValue1(ssa.OpSlicePtr, pt, r[0])
3614	l = s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], r[0])
3615	c = s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], r[0])
3616
3617	s.vars[ptrVar] = p
3618	s.vars[lenVar] = l
3619	s.vars[capVar] = c
3620	if inplace {
3621		if sn.Op() == ir.ONAME {
3622			sn := sn.(*ir.Name)
3623			if sn.Class != ir.PEXTERN {
3624				// Tell liveness we're about to build a new slice
3625				s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, sn, s.mem())
3626			}
3627		}
3628		capaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, types.SliceCapOffset, addr)
3629		s.store(types.Types[types.TINT], capaddr, c)
3630		s.store(pt, addr, p)
3631	}
3632
3633	b = s.endBlock()
3634	b.AddEdgeTo(assign)
3635
3636	// assign new elements to slots
3637	s.startBlock(assign)
3638	p = s.variable(ptrVar, pt)                      // generates phi for ptr
3639	l = s.variable(lenVar, types.Types[types.TINT]) // generates phi for len
3640	if !inplace {
3641		c = s.variable(capVar, types.Types[types.TINT]) // generates phi for cap
3642	}
3643
3644	if inplace {
3645		// Update length in place.
3646		// We have to wait until here to make sure growslice succeeded.
3647		lenaddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, types.SliceLenOffset, addr)
3648		s.store(types.Types[types.TINT], lenaddr, l)
3649	}
3650
3651	// Evaluate args
3652	type argRec struct {
3653		// if store is true, we're appending the value v.  If false, we're appending the
3654		// value at *v.
3655		v     *ssa.Value
3656		store bool
3657	}
3658	args := make([]argRec, 0, len(n.Args[1:]))
3659	for _, n := range n.Args[1:] {
3660		if ssa.CanSSA(n.Type()) {
3661			args = append(args, argRec{v: s.expr(n), store: true})
3662		} else {
3663			v := s.addr(n)
3664			args = append(args, argRec{v: v})
3665		}
3666	}
3667
3668	// Write args into slice.
3669	oldLen := s.newValue2(s.ssaOp(ir.OSUB, types.Types[types.TINT]), types.Types[types.TINT], l, nargs)
3670	p2 := s.newValue2(ssa.OpPtrIndex, pt, p, oldLen)
3671	for i, arg := range args {
3672		addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[types.TINT], int64(i)))
3673		if arg.store {
3674			s.storeType(et, addr, arg.v, 0, true)
3675		} else {
3676			s.move(et, addr, arg.v)
3677		}
3678	}
3679
3680	// The following deletions have no practical effect at this time
3681	// because state.vars has been reset by the preceding state.startBlock.
3682	// They only enforce the fact that these variables are no longer need in
3683	// the current scope.
3684	delete(s.vars, ptrVar)
3685	delete(s.vars, lenVar)
3686	if !inplace {
3687		delete(s.vars, capVar)
3688	}
3689
3690	// make result
3691	if inplace {
3692		return nil
3693	}
3694	return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
3695}
3696
3697// minMax converts an OMIN/OMAX builtin call into SSA.
3698func (s *state) minMax(n *ir.CallExpr) *ssa.Value {
3699	// The OMIN/OMAX builtin is variadic, but its semantics are
3700	// equivalent to left-folding a binary min/max operation across the
3701	// arguments list.
3702	fold := func(op func(x, a *ssa.Value) *ssa.Value) *ssa.Value {
3703		x := s.expr(n.Args[0])
3704		for _, arg := range n.Args[1:] {
3705			x = op(x, s.expr(arg))
3706		}
3707		return x
3708	}
3709
3710	typ := n.Type()
3711
3712	if typ.IsFloat() || typ.IsString() {
3713		// min/max semantics for floats are tricky because of NaNs and
3714		// negative zero. Some architectures have instructions which
3715		// we can use to generate the right result. For others we must
3716		// call into the runtime instead.
3717		//
3718		// Strings are conceptually simpler, but we currently desugar
3719		// string comparisons during walk, not ssagen.
3720
3721		if typ.IsFloat() {
3722			hasIntrinsic := false
3723			switch Arch.LinkArch.Family {
3724			case sys.AMD64, sys.ARM64, sys.RISCV64:
3725				hasIntrinsic = true
3726			case sys.PPC64:
3727				hasIntrinsic = buildcfg.GOPPC64 >= 9
3728			}
3729
3730			if hasIntrinsic {
3731				var op ssa.Op
3732				switch {
3733				case typ.Kind() == types.TFLOAT64 && n.Op() == ir.OMIN:
3734					op = ssa.OpMin64F
3735				case typ.Kind() == types.TFLOAT64 && n.Op() == ir.OMAX:
3736					op = ssa.OpMax64F
3737				case typ.Kind() == types.TFLOAT32 && n.Op() == ir.OMIN:
3738					op = ssa.OpMin32F
3739				case typ.Kind() == types.TFLOAT32 && n.Op() == ir.OMAX:
3740					op = ssa.OpMax32F
3741				}
3742				return fold(func(x, a *ssa.Value) *ssa.Value {
3743					return s.newValue2(op, typ, x, a)
3744				})
3745			}
3746		}
3747		var name string
3748		switch typ.Kind() {
3749		case types.TFLOAT32:
3750			switch n.Op() {
3751			case ir.OMIN:
3752				name = "fmin32"
3753			case ir.OMAX:
3754				name = "fmax32"
3755			}
3756		case types.TFLOAT64:
3757			switch n.Op() {
3758			case ir.OMIN:
3759				name = "fmin64"
3760			case ir.OMAX:
3761				name = "fmax64"
3762			}
3763		case types.TSTRING:
3764			switch n.Op() {
3765			case ir.OMIN:
3766				name = "strmin"
3767			case ir.OMAX:
3768				name = "strmax"
3769			}
3770		}
3771		fn := typecheck.LookupRuntimeFunc(name)
3772
3773		return fold(func(x, a *ssa.Value) *ssa.Value {
3774			return s.rtcall(fn, true, []*types.Type{typ}, x, a)[0]
3775		})
3776	}
3777
3778	lt := s.ssaOp(ir.OLT, typ)
3779
3780	return fold(func(x, a *ssa.Value) *ssa.Value {
3781		switch n.Op() {
3782		case ir.OMIN:
3783			// a < x ? a : x
3784			return s.ternary(s.newValue2(lt, types.Types[types.TBOOL], a, x), a, x)
3785		case ir.OMAX:
3786			// x < a ? a : x
3787			return s.ternary(s.newValue2(lt, types.Types[types.TBOOL], x, a), a, x)
3788		}
3789		panic("unreachable")
3790	})
3791}
3792
3793// ternary emits code to evaluate cond ? x : y.
3794func (s *state) ternary(cond, x, y *ssa.Value) *ssa.Value {
3795	// Note that we need a new ternaryVar each time (unlike okVar where we can
3796	// reuse the variable) because it might have a different type every time.
3797	ternaryVar := ssaMarker("ternary")
3798
3799	bThen := s.f.NewBlock(ssa.BlockPlain)
3800	bElse := s.f.NewBlock(ssa.BlockPlain)
3801	bEnd := s.f.NewBlock(ssa.BlockPlain)
3802
3803	b := s.endBlock()
3804	b.Kind = ssa.BlockIf
3805	b.SetControl(cond)
3806	b.AddEdgeTo(bThen)
3807	b.AddEdgeTo(bElse)
3808
3809	s.startBlock(bThen)
3810	s.vars[ternaryVar] = x
3811	s.endBlock().AddEdgeTo(bEnd)
3812
3813	s.startBlock(bElse)
3814	s.vars[ternaryVar] = y
3815	s.endBlock().AddEdgeTo(bEnd)
3816
3817	s.startBlock(bEnd)
3818	r := s.variable(ternaryVar, x.Type)
3819	delete(s.vars, ternaryVar)
3820	return r
3821}
3822
3823// condBranch evaluates the boolean expression cond and branches to yes
3824// if cond is true and no if cond is false.
3825// This function is intended to handle && and || better than just calling
3826// s.expr(cond) and branching on the result.
3827func (s *state) condBranch(cond ir.Node, yes, no *ssa.Block, likely int8) {
3828	switch cond.Op() {
3829	case ir.OANDAND:
3830		cond := cond.(*ir.LogicalExpr)
3831		mid := s.f.NewBlock(ssa.BlockPlain)
3832		s.stmtList(cond.Init())
3833		s.condBranch(cond.X, mid, no, max8(likely, 0))
3834		s.startBlock(mid)
3835		s.condBranch(cond.Y, yes, no, likely)
3836		return
3837		// Note: if likely==1, then both recursive calls pass 1.
3838		// If likely==-1, then we don't have enough information to decide
3839		// whether the first branch is likely or not. So we pass 0 for
3840		// the likeliness of the first branch.
3841		// TODO: have the frontend give us branch prediction hints for
3842		// OANDAND and OOROR nodes (if it ever has such info).
3843	case ir.OOROR:
3844		cond := cond.(*ir.LogicalExpr)
3845		mid := s.f.NewBlock(ssa.BlockPlain)
3846		s.stmtList(cond.Init())
3847		s.condBranch(cond.X, yes, mid, min8(likely, 0))
3848		s.startBlock(mid)
3849		s.condBranch(cond.Y, yes, no, likely)
3850		return
3851		// Note: if likely==-1, then both recursive calls pass -1.
3852		// If likely==1, then we don't have enough info to decide
3853		// the likelihood of the first branch.
3854	case ir.ONOT:
3855		cond := cond.(*ir.UnaryExpr)
3856		s.stmtList(cond.Init())
3857		s.condBranch(cond.X, no, yes, -likely)
3858		return
3859	case ir.OCONVNOP:
3860		cond := cond.(*ir.ConvExpr)
3861		s.stmtList(cond.Init())
3862		s.condBranch(cond.X, yes, no, likely)
3863		return
3864	}
3865	c := s.expr(cond)
3866	b := s.endBlock()
3867	b.Kind = ssa.BlockIf
3868	b.SetControl(c)
3869	b.Likely = ssa.BranchPrediction(likely) // gc and ssa both use -1/0/+1 for likeliness
3870	b.AddEdgeTo(yes)
3871	b.AddEdgeTo(no)
3872}
3873
3874type skipMask uint8
3875
3876const (
3877	skipPtr skipMask = 1 << iota
3878	skipLen
3879	skipCap
3880)
3881
3882// assign does left = right.
3883// Right has already been evaluated to ssa, left has not.
3884// If deref is true, then we do left = *right instead (and right has already been nil-checked).
3885// If deref is true and right == nil, just do left = 0.
3886// skip indicates assignments (at the top level) that can be avoided.
3887// mayOverlap indicates whether left&right might partially overlap in memory. Default is false.
3888func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask) {
3889	s.assignWhichMayOverlap(left, right, deref, skip, false)
3890}
3891func (s *state) assignWhichMayOverlap(left ir.Node, right *ssa.Value, deref bool, skip skipMask, mayOverlap bool) {
3892	if left.Op() == ir.ONAME && ir.IsBlank(left) {
3893		return
3894	}
3895	t := left.Type()
3896	types.CalcSize(t)
3897	if s.canSSA(left) {
3898		if deref {
3899			s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
3900		}
3901		if left.Op() == ir.ODOT {
3902			// We're assigning to a field of an ssa-able value.
3903			// We need to build a new structure with the new value for the
3904			// field we're assigning and the old values for the other fields.
3905			// For instance:
3906			//   type T struct {a, b, c int}
3907			//   var T x
3908			//   x.b = 5
3909			// For the x.b = 5 assignment we want to generate x = T{x.a, 5, x.c}
3910
3911			// Grab information about the structure type.
3912			left := left.(*ir.SelectorExpr)
3913			t := left.X.Type()
3914			nf := t.NumFields()
3915			idx := fieldIdx(left)
3916
3917			// Grab old value of structure.
3918			old := s.expr(left.X)
3919
3920			// Make new structure.
3921			new := s.newValue0(ssa.StructMakeOp(t.NumFields()), t)
3922
3923			// Add fields as args.
3924			for i := 0; i < nf; i++ {
3925				if i == idx {
3926					new.AddArg(right)
3927				} else {
3928					new.AddArg(s.newValue1I(ssa.OpStructSelect, t.FieldType(i), int64(i), old))
3929				}
3930			}
3931
3932			// Recursively assign the new value we've made to the base of the dot op.
3933			s.assign(left.X, new, false, 0)
3934			// TODO: do we need to update named values here?
3935			return
3936		}
3937		if left.Op() == ir.OINDEX && left.(*ir.IndexExpr).X.Type().IsArray() {
3938			left := left.(*ir.IndexExpr)
3939			s.pushLine(left.Pos())
3940			defer s.popLine()
3941			// We're assigning to an element of an ssa-able array.
3942			// a[i] = v
3943			t := left.X.Type()
3944			n := t.NumElem()
3945
3946			i := s.expr(left.Index) // index
3947			if n == 0 {
3948				// The bounds check must fail.  Might as well
3949				// ignore the actual index and just use zeros.
3950				z := s.constInt(types.Types[types.TINT], 0)
3951				s.boundsCheck(z, z, ssa.BoundsIndex, false)
3952				return
3953			}
3954			if n != 1 {
3955				s.Fatalf("assigning to non-1-length array")
3956			}
3957			// Rewrite to a = [1]{v}
3958			len := s.constInt(types.Types[types.TINT], 1)
3959			s.boundsCheck(i, len, ssa.BoundsIndex, false) // checks i == 0
3960			v := s.newValue1(ssa.OpArrayMake1, t, right)
3961			s.assign(left.X, v, false, 0)
3962			return
3963		}
3964		left := left.(*ir.Name)
3965		// Update variable assignment.
3966		s.vars[left] = right
3967		s.addNamedValue(left, right)
3968		return
3969	}
3970
3971	// If this assignment clobbers an entire local variable, then emit
3972	// OpVarDef so liveness analysis knows the variable is redefined.
3973	if base, ok := clobberBase(left).(*ir.Name); ok && base.OnStack() && skip == 0 && (t.HasPointers() || ssa.IsMergeCandidate(base)) {
3974		s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !ir.IsAutoTmp(base))
3975	}
3976
3977	// Left is not ssa-able. Compute its address.
3978	addr := s.addr(left)
3979	if ir.IsReflectHeaderDataField(left) {
3980		// Package unsafe's documentation says storing pointers into
3981		// reflect.SliceHeader and reflect.StringHeader's Data fields
3982		// is valid, even though they have type uintptr (#19168).
3983		// Mark it pointer type to signal the writebarrier pass to
3984		// insert a write barrier.
3985		t = types.Types[types.TUNSAFEPTR]
3986	}
3987	if deref {
3988		// Treat as a mem->mem move.
3989		if right == nil {
3990			s.zero(t, addr)
3991		} else {
3992			s.moveWhichMayOverlap(t, addr, right, mayOverlap)
3993		}
3994		return
3995	}
3996	// Treat as a store.
3997	s.storeType(t, addr, right, skip, !ir.IsAutoTmp(left))
3998}
3999
4000// zeroVal returns the zero value for type t.
4001func (s *state) zeroVal(t *types.Type) *ssa.Value {
4002	switch {
4003	case t.IsInteger():
4004		switch t.Size() {
4005		case 1:
4006			return s.constInt8(t, 0)
4007		case 2:
4008			return s.constInt16(t, 0)
4009		case 4:
4010			return s.constInt32(t, 0)
4011		case 8:
4012			return s.constInt64(t, 0)
4013		default:
4014			s.Fatalf("bad sized integer type %v", t)
4015		}
4016	case t.IsFloat():
4017		switch t.Size() {
4018		case 4:
4019			return s.constFloat32(t, 0)
4020		case 8:
4021			return s.constFloat64(t, 0)
4022		default:
4023			s.Fatalf("bad sized float type %v", t)
4024		}
4025	case t.IsComplex():
4026		switch t.Size() {
4027		case 8:
4028			z := s.constFloat32(types.Types[types.TFLOAT32], 0)
4029			return s.entryNewValue2(ssa.OpComplexMake, t, z, z)
4030		case 16:
4031			z := s.constFloat64(types.Types[types.TFLOAT64], 0)
4032			return s.entryNewValue2(ssa.OpComplexMake, t, z, z)
4033		default:
4034			s.Fatalf("bad sized complex type %v", t)
4035		}
4036
4037	case t.IsString():
4038		return s.constEmptyString(t)
4039	case t.IsPtrShaped():
4040		return s.constNil(t)
4041	case t.IsBoolean():
4042		return s.constBool(false)
4043	case t.IsInterface():
4044		return s.constInterface(t)
4045	case t.IsSlice():
4046		return s.constSlice(t)
4047	case t.IsStruct():
4048		n := t.NumFields()
4049		v := s.entryNewValue0(ssa.StructMakeOp(t.NumFields()), t)
4050		for i := 0; i < n; i++ {
4051			v.AddArg(s.zeroVal(t.FieldType(i)))
4052		}
4053		return v
4054	case t.IsArray():
4055		switch t.NumElem() {
4056		case 0:
4057			return s.entryNewValue0(ssa.OpArrayMake0, t)
4058		case 1:
4059			return s.entryNewValue1(ssa.OpArrayMake1, t, s.zeroVal(t.Elem()))
4060		}
4061	}
4062	s.Fatalf("zero for type %v not implemented", t)
4063	return nil
4064}
4065
4066type callKind int8
4067
4068const (
4069	callNormal callKind = iota
4070	callDefer
4071	callDeferStack
4072	callGo
4073	callTail
4074)
4075
4076type sfRtCallDef struct {
4077	rtfn  *obj.LSym
4078	rtype types.Kind
4079}
4080
4081var softFloatOps map[ssa.Op]sfRtCallDef
4082
4083func softfloatInit() {
4084	// Some of these operations get transformed by sfcall.
4085	softFloatOps = map[ssa.Op]sfRtCallDef{
4086		ssa.OpAdd32F: {typecheck.LookupRuntimeFunc("fadd32"), types.TFLOAT32},
4087		ssa.OpAdd64F: {typecheck.LookupRuntimeFunc("fadd64"), types.TFLOAT64},
4088		ssa.OpSub32F: {typecheck.LookupRuntimeFunc("fadd32"), types.TFLOAT32},
4089		ssa.OpSub64F: {typecheck.LookupRuntimeFunc("fadd64"), types.TFLOAT64},
4090		ssa.OpMul32F: {typecheck.LookupRuntimeFunc("fmul32"), types.TFLOAT32},
4091		ssa.OpMul64F: {typecheck.LookupRuntimeFunc("fmul64"), types.TFLOAT64},
4092		ssa.OpDiv32F: {typecheck.LookupRuntimeFunc("fdiv32"), types.TFLOAT32},
4093		ssa.OpDiv64F: {typecheck.LookupRuntimeFunc("fdiv64"), types.TFLOAT64},
4094
4095		ssa.OpEq64F:   {typecheck.LookupRuntimeFunc("feq64"), types.TBOOL},
4096		ssa.OpEq32F:   {typecheck.LookupRuntimeFunc("feq32"), types.TBOOL},
4097		ssa.OpNeq64F:  {typecheck.LookupRuntimeFunc("feq64"), types.TBOOL},
4098		ssa.OpNeq32F:  {typecheck.LookupRuntimeFunc("feq32"), types.TBOOL},
4099		ssa.OpLess64F: {typecheck.LookupRuntimeFunc("fgt64"), types.TBOOL},
4100		ssa.OpLess32F: {typecheck.LookupRuntimeFunc("fgt32"), types.TBOOL},
4101		ssa.OpLeq64F:  {typecheck.LookupRuntimeFunc("fge64"), types.TBOOL},
4102		ssa.OpLeq32F:  {typecheck.LookupRuntimeFunc("fge32"), types.TBOOL},
4103
4104		ssa.OpCvt32to32F:  {typecheck.LookupRuntimeFunc("fint32to32"), types.TFLOAT32},
4105		ssa.OpCvt32Fto32:  {typecheck.LookupRuntimeFunc("f32toint32"), types.TINT32},
4106		ssa.OpCvt64to32F:  {typecheck.LookupRuntimeFunc("fint64to32"), types.TFLOAT32},
4107		ssa.OpCvt32Fto64:  {typecheck.LookupRuntimeFunc("f32toint64"), types.TINT64},
4108		ssa.OpCvt64Uto32F: {typecheck.LookupRuntimeFunc("fuint64to32"), types.TFLOAT32},
4109		ssa.OpCvt32Fto64U: {typecheck.LookupRuntimeFunc("f32touint64"), types.TUINT64},
4110		ssa.OpCvt32to64F:  {typecheck.LookupRuntimeFunc("fint32to64"), types.TFLOAT64},
4111		ssa.OpCvt64Fto32:  {typecheck.LookupRuntimeFunc("f64toint32"), types.TINT32},
4112		ssa.OpCvt64to64F:  {typecheck.LookupRuntimeFunc("fint64to64"), types.TFLOAT64},
4113		ssa.OpCvt64Fto64:  {typecheck.LookupRuntimeFunc("f64toint64"), types.TINT64},
4114		ssa.OpCvt64Uto64F: {typecheck.LookupRuntimeFunc("fuint64to64"), types.TFLOAT64},
4115		ssa.OpCvt64Fto64U: {typecheck.LookupRuntimeFunc("f64touint64"), types.TUINT64},
4116		ssa.OpCvt32Fto64F: {typecheck.LookupRuntimeFunc("f32to64"), types.TFLOAT64},
4117		ssa.OpCvt64Fto32F: {typecheck.LookupRuntimeFunc("f64to32"), types.TFLOAT32},
4118	}
4119}
4120
4121// TODO: do not emit sfcall if operation can be optimized to constant in later
4122// opt phase
4123func (s *state) sfcall(op ssa.Op, args ...*ssa.Value) (*ssa.Value, bool) {
4124	f2i := func(t *types.Type) *types.Type {
4125		switch t.Kind() {
4126		case types.TFLOAT32:
4127			return types.Types[types.TUINT32]
4128		case types.TFLOAT64:
4129			return types.Types[types.TUINT64]
4130		}
4131		return t
4132	}
4133
4134	if callDef, ok := softFloatOps[op]; ok {
4135		switch op {
4136		case ssa.OpLess32F,
4137			ssa.OpLess64F,
4138			ssa.OpLeq32F,
4139			ssa.OpLeq64F:
4140			args[0], args[1] = args[1], args[0]
4141		case ssa.OpSub32F,
4142			ssa.OpSub64F:
4143			args[1] = s.newValue1(s.ssaOp(ir.ONEG, types.Types[callDef.rtype]), args[1].Type, args[1])
4144		}
4145
4146		// runtime functions take uints for floats and returns uints.
4147		// Convert to uints so we use the right calling convention.
4148		for i, a := range args {
4149			if a.Type.IsFloat() {
4150				args[i] = s.newValue1(ssa.OpCopy, f2i(a.Type), a)
4151			}
4152		}
4153
4154		rt := types.Types[callDef.rtype]
4155		result := s.rtcall(callDef.rtfn, true, []*types.Type{f2i(rt)}, args...)[0]
4156		if rt.IsFloat() {
4157			result = s.newValue1(ssa.OpCopy, rt, result)
4158		}
4159		if op == ssa.OpNeq32F || op == ssa.OpNeq64F {
4160			result = s.newValue1(ssa.OpNot, result.Type, result)
4161		}
4162		return result, true
4163	}
4164	return nil, false
4165}
4166
4167var intrinsics map[intrinsicKey]intrinsicBuilder
4168
4169// An intrinsicBuilder converts a call node n into an ssa value that
4170// implements that call as an intrinsic. args is a list of arguments to the func.
4171type intrinsicBuilder func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value
4172
4173type intrinsicKey struct {
4174	arch *sys.Arch
4175	pkg  string
4176	fn   string
4177}
4178
4179func InitTables() {
4180	intrinsics = map[intrinsicKey]intrinsicBuilder{}
4181
4182	var all []*sys.Arch
4183	var p4 []*sys.Arch
4184	var p8 []*sys.Arch
4185	var lwatomics []*sys.Arch
4186	for _, a := range &sys.Archs {
4187		all = append(all, a)
4188		if a.PtrSize == 4 {
4189			p4 = append(p4, a)
4190		} else {
4191			p8 = append(p8, a)
4192		}
4193		if a.Family != sys.PPC64 {
4194			lwatomics = append(lwatomics, a)
4195		}
4196	}
4197
4198	// add adds the intrinsic b for pkg.fn for the given list of architectures.
4199	add := func(pkg, fn string, b intrinsicBuilder, archs ...*sys.Arch) {
4200		for _, a := range archs {
4201			intrinsics[intrinsicKey{a, pkg, fn}] = b
4202		}
4203	}
4204	// addF does the same as add but operates on architecture families.
4205	addF := func(pkg, fn string, b intrinsicBuilder, archFamilies ...sys.ArchFamily) {
4206		m := 0
4207		for _, f := range archFamilies {
4208			if f >= 32 {
4209				panic("too many architecture families")
4210			}
4211			m |= 1 << uint(f)
4212		}
4213		for _, a := range all {
4214			if m>>uint(a.Family)&1 != 0 {
4215				intrinsics[intrinsicKey{a, pkg, fn}] = b
4216			}
4217		}
4218	}
4219	// alias defines pkg.fn = pkg2.fn2 for all architectures in archs for which pkg2.fn2 exists.
4220	alias := func(pkg, fn, pkg2, fn2 string, archs ...*sys.Arch) {
4221		aliased := false
4222		for _, a := range archs {
4223			if b, ok := intrinsics[intrinsicKey{a, pkg2, fn2}]; ok {
4224				intrinsics[intrinsicKey{a, pkg, fn}] = b
4225				aliased = true
4226			}
4227		}
4228		if !aliased {
4229			panic(fmt.Sprintf("attempted to alias undefined intrinsic: %s.%s", pkg, fn))
4230		}
4231	}
4232
4233	/******** runtime ********/
4234	if !base.Flag.Cfg.Instrumenting {
4235		add("runtime", "slicebytetostringtmp",
4236			func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4237				// Compiler frontend optimizations emit OBYTES2STRTMP nodes
4238				// for the backend instead of slicebytetostringtmp calls
4239				// when not instrumenting.
4240				return s.newValue2(ssa.OpStringMake, n.Type(), args[0], args[1])
4241			},
4242			all...)
4243	}
4244	addF("runtime/internal/math", "MulUintptr",
4245		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4246			if s.config.PtrSize == 4 {
4247				return s.newValue2(ssa.OpMul32uover, types.NewTuple(types.Types[types.TUINT], types.Types[types.TUINT]), args[0], args[1])
4248			}
4249			return s.newValue2(ssa.OpMul64uover, types.NewTuple(types.Types[types.TUINT], types.Types[types.TUINT]), args[0], args[1])
4250		},
4251		sys.AMD64, sys.I386, sys.Loong64, sys.MIPS64, sys.RISCV64, sys.ARM64)
4252	add("runtime", "KeepAlive",
4253		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4254			data := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, args[0])
4255			s.vars[memVar] = s.newValue2(ssa.OpKeepAlive, types.TypeMem, data, s.mem())
4256			return nil
4257		},
4258		all...)
4259	add("runtime", "getclosureptr",
4260		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4261			return s.newValue0(ssa.OpGetClosurePtr, s.f.Config.Types.Uintptr)
4262		},
4263		all...)
4264
4265	add("runtime", "getcallerpc",
4266		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4267			return s.newValue0(ssa.OpGetCallerPC, s.f.Config.Types.Uintptr)
4268		},
4269		all...)
4270
4271	add("runtime", "getcallersp",
4272		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4273			return s.newValue1(ssa.OpGetCallerSP, s.f.Config.Types.Uintptr, s.mem())
4274		},
4275		all...)
4276
4277	addF("runtime", "publicationBarrier",
4278		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4279			s.vars[memVar] = s.newValue1(ssa.OpPubBarrier, types.TypeMem, s.mem())
4280			return nil
4281		},
4282		sys.ARM64, sys.PPC64, sys.RISCV64)
4283
4284	brev_arch := []sys.ArchFamily{sys.AMD64, sys.I386, sys.ARM64, sys.ARM, sys.S390X}
4285	if buildcfg.GOPPC64 >= 10 {
4286		// Use only on Power10 as the new byte reverse instructions that Power10 provide
4287		// make it worthwhile as an intrinsic
4288		brev_arch = append(brev_arch, sys.PPC64)
4289	}
4290	/******** runtime/internal/sys ********/
4291	addF("runtime/internal/sys", "Bswap32",
4292		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4293			return s.newValue1(ssa.OpBswap32, types.Types[types.TUINT32], args[0])
4294		},
4295		brev_arch...)
4296	addF("runtime/internal/sys", "Bswap64",
4297		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4298			return s.newValue1(ssa.OpBswap64, types.Types[types.TUINT64], args[0])
4299		},
4300		brev_arch...)
4301
4302	/****** Prefetch ******/
4303	makePrefetchFunc := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4304		return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4305			s.vars[memVar] = s.newValue2(op, types.TypeMem, args[0], s.mem())
4306			return nil
4307		}
4308	}
4309
4310	// Make Prefetch intrinsics for supported platforms
4311	// On the unsupported platforms stub function will be eliminated
4312	addF("runtime/internal/sys", "Prefetch", makePrefetchFunc(ssa.OpPrefetchCache),
4313		sys.AMD64, sys.ARM64, sys.PPC64)
4314	addF("runtime/internal/sys", "PrefetchStreamed", makePrefetchFunc(ssa.OpPrefetchCacheStreamed),
4315		sys.AMD64, sys.ARM64, sys.PPC64)
4316
4317	/******** internal/runtime/atomic ********/
4318	addF("internal/runtime/atomic", "Load",
4319		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4320			v := s.newValue2(ssa.OpAtomicLoad32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], s.mem())
4321			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4322			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v)
4323		},
4324		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4325	addF("internal/runtime/atomic", "Load8",
4326		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4327			v := s.newValue2(ssa.OpAtomicLoad8, types.NewTuple(types.Types[types.TUINT8], types.TypeMem), args[0], s.mem())
4328			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4329			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT8], v)
4330		},
4331		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4332	addF("internal/runtime/atomic", "Load64",
4333		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4334			v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], s.mem())
4335			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4336			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v)
4337		},
4338		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4339	addF("internal/runtime/atomic", "LoadAcq",
4340		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4341			v := s.newValue2(ssa.OpAtomicLoadAcq32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], s.mem())
4342			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4343			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v)
4344		},
4345		sys.PPC64, sys.S390X)
4346	addF("internal/runtime/atomic", "LoadAcq64",
4347		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4348			v := s.newValue2(ssa.OpAtomicLoadAcq64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], s.mem())
4349			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4350			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v)
4351		},
4352		sys.PPC64)
4353	addF("internal/runtime/atomic", "Loadp",
4354		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4355			v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem())
4356			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4357			return s.newValue1(ssa.OpSelect0, s.f.Config.Types.BytePtr, v)
4358		},
4359		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4360
4361	addF("internal/runtime/atomic", "Store",
4362		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4363			s.vars[memVar] = s.newValue3(ssa.OpAtomicStore32, types.TypeMem, args[0], args[1], s.mem())
4364			return nil
4365		},
4366		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4367	addF("internal/runtime/atomic", "Store8",
4368		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4369			s.vars[memVar] = s.newValue3(ssa.OpAtomicStore8, types.TypeMem, args[0], args[1], s.mem())
4370			return nil
4371		},
4372		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4373	addF("internal/runtime/atomic", "Store64",
4374		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4375			s.vars[memVar] = s.newValue3(ssa.OpAtomicStore64, types.TypeMem, args[0], args[1], s.mem())
4376			return nil
4377		},
4378		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4379	addF("internal/runtime/atomic", "StorepNoWB",
4380		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4381			s.vars[memVar] = s.newValue3(ssa.OpAtomicStorePtrNoWB, types.TypeMem, args[0], args[1], s.mem())
4382			return nil
4383		},
4384		sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.RISCV64, sys.S390X)
4385	addF("internal/runtime/atomic", "StoreRel",
4386		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4387			s.vars[memVar] = s.newValue3(ssa.OpAtomicStoreRel32, types.TypeMem, args[0], args[1], s.mem())
4388			return nil
4389		},
4390		sys.PPC64, sys.S390X)
4391	addF("internal/runtime/atomic", "StoreRel64",
4392		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4393			s.vars[memVar] = s.newValue3(ssa.OpAtomicStoreRel64, types.TypeMem, args[0], args[1], s.mem())
4394			return nil
4395		},
4396		sys.PPC64)
4397
4398	addF("internal/runtime/atomic", "Xchg",
4399		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4400			v := s.newValue3(ssa.OpAtomicExchange32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem())
4401			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4402			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v)
4403		},
4404		sys.AMD64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4405	addF("internal/runtime/atomic", "Xchg64",
4406		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4407			v := s.newValue3(ssa.OpAtomicExchange64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], args[1], s.mem())
4408			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4409			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v)
4410		},
4411		sys.AMD64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4412
4413	type atomicOpEmitter func(s *state, n *ir.CallExpr, args []*ssa.Value, op ssa.Op, typ types.Kind)
4414
4415	makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ types.Kind, emit atomicOpEmitter) intrinsicBuilder {
4416
4417		return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4418			if buildcfg.GOARM64.LSE {
4419				emit(s, n, args, op1, typ)
4420			} else {
4421				// Target Atomic feature is identified by dynamic detection
4422				addr := s.entryNewValue1A(ssa.OpAddr, types.Types[types.TBOOL].PtrTo(), ir.Syms.ARM64HasATOMICS, s.sb)
4423				v := s.load(types.Types[types.TBOOL], addr)
4424				b := s.endBlock()
4425				b.Kind = ssa.BlockIf
4426				b.SetControl(v)
4427				bTrue := s.f.NewBlock(ssa.BlockPlain)
4428				bFalse := s.f.NewBlock(ssa.BlockPlain)
4429				bEnd := s.f.NewBlock(ssa.BlockPlain)
4430				b.AddEdgeTo(bTrue)
4431				b.AddEdgeTo(bFalse)
4432				b.Likely = ssa.BranchLikely
4433
4434				// We have atomic instructions - use it directly.
4435				s.startBlock(bTrue)
4436				emit(s, n, args, op1, typ)
4437				s.endBlock().AddEdgeTo(bEnd)
4438
4439				// Use original instruction sequence.
4440				s.startBlock(bFalse)
4441				emit(s, n, args, op0, typ)
4442				s.endBlock().AddEdgeTo(bEnd)
4443
4444				// Merge results.
4445				s.startBlock(bEnd)
4446			}
4447			if typ == types.TNIL {
4448				return nil
4449			} else {
4450				return s.variable(n, types.Types[typ])
4451			}
4452		}
4453	}
4454
4455	atomicEmitterARM64 := func(s *state, n *ir.CallExpr, args []*ssa.Value, op ssa.Op, typ types.Kind) {
4456		v := s.newValue3(op, types.NewTuple(types.Types[typ], types.TypeMem), args[0], args[1], s.mem())
4457		s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4458		s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v)
4459	}
4460	addF("internal/runtime/atomic", "Xchg",
4461		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange32, ssa.OpAtomicExchange32Variant, types.TUINT32, atomicEmitterARM64),
4462		sys.ARM64)
4463	addF("internal/runtime/atomic", "Xchg64",
4464		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange64, ssa.OpAtomicExchange64Variant, types.TUINT64, atomicEmitterARM64),
4465		sys.ARM64)
4466
4467	addF("internal/runtime/atomic", "Xadd",
4468		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4469			v := s.newValue3(ssa.OpAtomicAdd32, types.NewTuple(types.Types[types.TUINT32], types.TypeMem), args[0], args[1], s.mem())
4470			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4471			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT32], v)
4472		},
4473		sys.AMD64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4474	addF("internal/runtime/atomic", "Xadd64",
4475		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4476			v := s.newValue3(ssa.OpAtomicAdd64, types.NewTuple(types.Types[types.TUINT64], types.TypeMem), args[0], args[1], s.mem())
4477			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4478			return s.newValue1(ssa.OpSelect0, types.Types[types.TUINT64], v)
4479		},
4480		sys.AMD64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4481
4482	addF("internal/runtime/atomic", "Xadd",
4483		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, types.TUINT32, atomicEmitterARM64),
4484		sys.ARM64)
4485	addF("internal/runtime/atomic", "Xadd64",
4486		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, types.TUINT64, atomicEmitterARM64),
4487		sys.ARM64)
4488
4489	addF("internal/runtime/atomic", "Cas",
4490		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4491			v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
4492			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4493			return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v)
4494		},
4495		sys.AMD64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4496	addF("internal/runtime/atomic", "Cas64",
4497		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4498			v := s.newValue4(ssa.OpAtomicCompareAndSwap64, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
4499			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4500			return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v)
4501		},
4502		sys.AMD64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4503	addF("internal/runtime/atomic", "CasRel",
4504		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4505			v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
4506			s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4507			return s.newValue1(ssa.OpSelect0, types.Types[types.TBOOL], v)
4508		},
4509		sys.PPC64)
4510
4511	atomicCasEmitterARM64 := func(s *state, n *ir.CallExpr, args []*ssa.Value, op ssa.Op, typ types.Kind) {
4512		v := s.newValue4(op, types.NewTuple(types.Types[types.TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem())
4513		s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
4514		s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v)
4515	}
4516
4517	addF("internal/runtime/atomic", "Cas",
4518		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap32, ssa.OpAtomicCompareAndSwap32Variant, types.TBOOL, atomicCasEmitterARM64),
4519		sys.ARM64)
4520	addF("internal/runtime/atomic", "Cas64",
4521		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap64, ssa.OpAtomicCompareAndSwap64Variant, types.TBOOL, atomicCasEmitterARM64),
4522		sys.ARM64)
4523
4524	addF("internal/runtime/atomic", "And8",
4525		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4526			s.vars[memVar] = s.newValue3(ssa.OpAtomicAnd8, types.TypeMem, args[0], args[1], s.mem())
4527			return nil
4528		},
4529		sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4530	addF("internal/runtime/atomic", "And",
4531		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4532			s.vars[memVar] = s.newValue3(ssa.OpAtomicAnd32, types.TypeMem, args[0], args[1], s.mem())
4533			return nil
4534		},
4535		sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4536	addF("internal/runtime/atomic", "Or8",
4537		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4538			s.vars[memVar] = s.newValue3(ssa.OpAtomicOr8, types.TypeMem, args[0], args[1], s.mem())
4539			return nil
4540		},
4541		sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4542	addF("internal/runtime/atomic", "Or",
4543		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4544			s.vars[memVar] = s.newValue3(ssa.OpAtomicOr32, types.TypeMem, args[0], args[1], s.mem())
4545			return nil
4546		},
4547		sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X)
4548
4549	addF("internal/runtime/atomic", "And8",
4550		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd8, ssa.OpAtomicAnd8Variant, types.TUINT8, atomicEmitterARM64),
4551		sys.ARM64)
4552	addF("internal/runtime/atomic", "Or8",
4553		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr8, ssa.OpAtomicOr8Variant, types.TUINT8, atomicEmitterARM64),
4554		sys.ARM64)
4555	addF("internal/runtime/atomic", "And64",
4556		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd64, ssa.OpAtomicAnd64Variant, types.TUINT64, atomicEmitterARM64),
4557		sys.ARM64)
4558	addF("internal/runtime/atomic", "And32",
4559		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd32, ssa.OpAtomicAnd32Variant, types.TUINT32, atomicEmitterARM64),
4560		sys.ARM64)
4561	addF("internal/runtime/atomic", "And",
4562		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd32, ssa.OpAtomicAnd32Variant, types.TUINT32, atomicEmitterARM64),
4563		sys.ARM64)
4564	addF("internal/runtime/atomic", "Or64",
4565		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr64, ssa.OpAtomicOr64Variant, types.TUINT64, atomicEmitterARM64),
4566		sys.ARM64)
4567	addF("internal/runtime/atomic", "Or32",
4568		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr32, ssa.OpAtomicOr32Variant, types.TUINT32, atomicEmitterARM64),
4569		sys.ARM64)
4570	addF("internal/runtime/atomic", "Or",
4571		makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr32, ssa.OpAtomicOr32Variant, types.TUINT32, atomicEmitterARM64),
4572		sys.ARM64)
4573
4574	// Aliases for atomic load operations
4575	alias("internal/runtime/atomic", "Loadint32", "internal/runtime/atomic", "Load", all...)
4576	alias("internal/runtime/atomic", "Loadint64", "internal/runtime/atomic", "Load64", all...)
4577	alias("internal/runtime/atomic", "Loaduintptr", "internal/runtime/atomic", "Load", p4...)
4578	alias("internal/runtime/atomic", "Loaduintptr", "internal/runtime/atomic", "Load64", p8...)
4579	alias("internal/runtime/atomic", "Loaduint", "internal/runtime/atomic", "Load", p4...)
4580	alias("internal/runtime/atomic", "Loaduint", "internal/runtime/atomic", "Load64", p8...)
4581	alias("internal/runtime/atomic", "LoadAcq", "internal/runtime/atomic", "Load", lwatomics...)
4582	alias("internal/runtime/atomic", "LoadAcq64", "internal/runtime/atomic", "Load64", lwatomics...)
4583	alias("internal/runtime/atomic", "LoadAcquintptr", "internal/runtime/atomic", "LoadAcq", p4...)
4584	alias("sync", "runtime_LoadAcquintptr", "internal/runtime/atomic", "LoadAcq", p4...) // linknamed
4585	alias("internal/runtime/atomic", "LoadAcquintptr", "internal/runtime/atomic", "LoadAcq64", p8...)
4586	alias("sync", "runtime_LoadAcquintptr", "internal/runtime/atomic", "LoadAcq64", p8...) // linknamed
4587
4588	// Aliases for atomic store operations
4589	alias("internal/runtime/atomic", "Storeint32", "internal/runtime/atomic", "Store", all...)
4590	alias("internal/runtime/atomic", "Storeint64", "internal/runtime/atomic", "Store64", all...)
4591	alias("internal/runtime/atomic", "Storeuintptr", "internal/runtime/atomic", "Store", p4...)
4592	alias("internal/runtime/atomic", "Storeuintptr", "internal/runtime/atomic", "Store64", p8...)
4593	alias("internal/runtime/atomic", "StoreRel", "internal/runtime/atomic", "Store", lwatomics...)
4594	alias("internal/runtime/atomic", "StoreRel64", "internal/runtime/atomic", "Store64", lwatomics...)
4595	alias("internal/runtime/atomic", "StoreReluintptr", "internal/runtime/atomic", "StoreRel", p4...)
4596	alias("sync", "runtime_StoreReluintptr", "internal/runtime/atomic", "StoreRel", p4...) // linknamed
4597	alias("internal/runtime/atomic", "StoreReluintptr", "internal/runtime/atomic", "StoreRel64", p8...)
4598	alias("sync", "runtime_StoreReluintptr", "internal/runtime/atomic", "StoreRel64", p8...) // linknamed
4599
4600	// Aliases for atomic swap operations
4601	alias("internal/runtime/atomic", "Xchgint32", "internal/runtime/atomic", "Xchg", all...)
4602	alias("internal/runtime/atomic", "Xchgint64", "internal/runtime/atomic", "Xchg64", all...)
4603	alias("internal/runtime/atomic", "Xchguintptr", "internal/runtime/atomic", "Xchg", p4...)
4604	alias("internal/runtime/atomic", "Xchguintptr", "internal/runtime/atomic", "Xchg64", p8...)
4605
4606	// Aliases for atomic add operations
4607	alias("internal/runtime/atomic", "Xaddint32", "internal/runtime/atomic", "Xadd", all...)
4608	alias("internal/runtime/atomic", "Xaddint64", "internal/runtime/atomic", "Xadd64", all...)
4609	alias("internal/runtime/atomic", "Xadduintptr", "internal/runtime/atomic", "Xadd", p4...)
4610	alias("internal/runtime/atomic", "Xadduintptr", "internal/runtime/atomic", "Xadd64", p8...)
4611
4612	// Aliases for atomic CAS operations
4613	alias("internal/runtime/atomic", "Casint32", "internal/runtime/atomic", "Cas", all...)
4614	alias("internal/runtime/atomic", "Casint64", "internal/runtime/atomic", "Cas64", all...)
4615	alias("internal/runtime/atomic", "Casuintptr", "internal/runtime/atomic", "Cas", p4...)
4616	alias("internal/runtime/atomic", "Casuintptr", "internal/runtime/atomic", "Cas64", p8...)
4617	alias("internal/runtime/atomic", "Casp1", "internal/runtime/atomic", "Cas", p4...)
4618	alias("internal/runtime/atomic", "Casp1", "internal/runtime/atomic", "Cas64", p8...)
4619	alias("internal/runtime/atomic", "CasRel", "internal/runtime/atomic", "Cas", lwatomics...)
4620
4621	// Aliases for atomic And/Or operations
4622	alias("internal/runtime/atomic", "Anduintptr", "internal/runtime/atomic", "And64", sys.ArchARM64)
4623	alias("internal/runtime/atomic", "Oruintptr", "internal/runtime/atomic", "Or64", sys.ArchARM64)
4624
4625	/******** math ********/
4626	addF("math", "sqrt",
4627		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4628			return s.newValue1(ssa.OpSqrt, types.Types[types.TFLOAT64], args[0])
4629		},
4630		sys.I386, sys.AMD64, sys.ARM, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm)
4631	addF("math", "Trunc",
4632		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4633			return s.newValue1(ssa.OpTrunc, types.Types[types.TFLOAT64], args[0])
4634		},
4635		sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm)
4636	addF("math", "Ceil",
4637		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4638			return s.newValue1(ssa.OpCeil, types.Types[types.TFLOAT64], args[0])
4639		},
4640		sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm)
4641	addF("math", "Floor",
4642		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4643			return s.newValue1(ssa.OpFloor, types.Types[types.TFLOAT64], args[0])
4644		},
4645		sys.ARM64, sys.PPC64, sys.S390X, sys.Wasm)
4646	addF("math", "Round",
4647		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4648			return s.newValue1(ssa.OpRound, types.Types[types.TFLOAT64], args[0])
4649		},
4650		sys.ARM64, sys.PPC64, sys.S390X)
4651	addF("math", "RoundToEven",
4652		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4653			return s.newValue1(ssa.OpRoundToEven, types.Types[types.TFLOAT64], args[0])
4654		},
4655		sys.ARM64, sys.S390X, sys.Wasm)
4656	addF("math", "Abs",
4657		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4658			return s.newValue1(ssa.OpAbs, types.Types[types.TFLOAT64], args[0])
4659		},
4660		sys.ARM64, sys.ARM, sys.PPC64, sys.RISCV64, sys.Wasm, sys.MIPS, sys.MIPS64)
4661	addF("math", "Copysign",
4662		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4663			return s.newValue2(ssa.OpCopysign, types.Types[types.TFLOAT64], args[0], args[1])
4664		},
4665		sys.PPC64, sys.RISCV64, sys.Wasm)
4666	addF("math", "FMA",
4667		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4668			return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2])
4669		},
4670		sys.ARM64, sys.PPC64, sys.RISCV64, sys.S390X)
4671	addF("math", "FMA",
4672		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4673			if !s.config.UseFMA {
4674				s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
4675				return s.variable(n, types.Types[types.TFLOAT64])
4676			}
4677
4678			if buildcfg.GOAMD64 >= 3 {
4679				return s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2])
4680			}
4681
4682			v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasFMA)
4683			b := s.endBlock()
4684			b.Kind = ssa.BlockIf
4685			b.SetControl(v)
4686			bTrue := s.f.NewBlock(ssa.BlockPlain)
4687			bFalse := s.f.NewBlock(ssa.BlockPlain)
4688			bEnd := s.f.NewBlock(ssa.BlockPlain)
4689			b.AddEdgeTo(bTrue)
4690			b.AddEdgeTo(bFalse)
4691			b.Likely = ssa.BranchLikely // >= haswell cpus are common
4692
4693			// We have the intrinsic - use it directly.
4694			s.startBlock(bTrue)
4695			s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2])
4696			s.endBlock().AddEdgeTo(bEnd)
4697
4698			// Call the pure Go version.
4699			s.startBlock(bFalse)
4700			s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
4701			s.endBlock().AddEdgeTo(bEnd)
4702
4703			// Merge results.
4704			s.startBlock(bEnd)
4705			return s.variable(n, types.Types[types.TFLOAT64])
4706		},
4707		sys.AMD64)
4708	addF("math", "FMA",
4709		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4710			if !s.config.UseFMA {
4711				s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
4712				return s.variable(n, types.Types[types.TFLOAT64])
4713			}
4714			addr := s.entryNewValue1A(ssa.OpAddr, types.Types[types.TBOOL].PtrTo(), ir.Syms.ARMHasVFPv4, s.sb)
4715			v := s.load(types.Types[types.TBOOL], addr)
4716			b := s.endBlock()
4717			b.Kind = ssa.BlockIf
4718			b.SetControl(v)
4719			bTrue := s.f.NewBlock(ssa.BlockPlain)
4720			bFalse := s.f.NewBlock(ssa.BlockPlain)
4721			bEnd := s.f.NewBlock(ssa.BlockPlain)
4722			b.AddEdgeTo(bTrue)
4723			b.AddEdgeTo(bFalse)
4724			b.Likely = ssa.BranchLikely
4725
4726			// We have the intrinsic - use it directly.
4727			s.startBlock(bTrue)
4728			s.vars[n] = s.newValue3(ssa.OpFMA, types.Types[types.TFLOAT64], args[0], args[1], args[2])
4729			s.endBlock().AddEdgeTo(bEnd)
4730
4731			// Call the pure Go version.
4732			s.startBlock(bFalse)
4733			s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
4734			s.endBlock().AddEdgeTo(bEnd)
4735
4736			// Merge results.
4737			s.startBlock(bEnd)
4738			return s.variable(n, types.Types[types.TFLOAT64])
4739		},
4740		sys.ARM)
4741
4742	makeRoundAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4743		return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4744			if buildcfg.GOAMD64 >= 2 {
4745				return s.newValue1(op, types.Types[types.TFLOAT64], args[0])
4746			}
4747
4748			v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasSSE41)
4749			b := s.endBlock()
4750			b.Kind = ssa.BlockIf
4751			b.SetControl(v)
4752			bTrue := s.f.NewBlock(ssa.BlockPlain)
4753			bFalse := s.f.NewBlock(ssa.BlockPlain)
4754			bEnd := s.f.NewBlock(ssa.BlockPlain)
4755			b.AddEdgeTo(bTrue)
4756			b.AddEdgeTo(bFalse)
4757			b.Likely = ssa.BranchLikely // most machines have sse4.1 nowadays
4758
4759			// We have the intrinsic - use it directly.
4760			s.startBlock(bTrue)
4761			s.vars[n] = s.newValue1(op, types.Types[types.TFLOAT64], args[0])
4762			s.endBlock().AddEdgeTo(bEnd)
4763
4764			// Call the pure Go version.
4765			s.startBlock(bFalse)
4766			s.vars[n] = s.callResult(n, callNormal) // types.Types[TFLOAT64]
4767			s.endBlock().AddEdgeTo(bEnd)
4768
4769			// Merge results.
4770			s.startBlock(bEnd)
4771			return s.variable(n, types.Types[types.TFLOAT64])
4772		}
4773	}
4774	addF("math", "RoundToEven",
4775		makeRoundAMD64(ssa.OpRoundToEven),
4776		sys.AMD64)
4777	addF("math", "Floor",
4778		makeRoundAMD64(ssa.OpFloor),
4779		sys.AMD64)
4780	addF("math", "Ceil",
4781		makeRoundAMD64(ssa.OpCeil),
4782		sys.AMD64)
4783	addF("math", "Trunc",
4784		makeRoundAMD64(ssa.OpTrunc),
4785		sys.AMD64)
4786
4787	/******** math/bits ********/
4788	addF("math/bits", "TrailingZeros64",
4789		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4790			return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], args[0])
4791		},
4792		sys.AMD64, sys.I386, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4793	addF("math/bits", "TrailingZeros32",
4794		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4795			return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], args[0])
4796		},
4797		sys.AMD64, sys.I386, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4798	addF("math/bits", "TrailingZeros16",
4799		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4800			x := s.newValue1(ssa.OpZeroExt16to32, types.Types[types.TUINT32], args[0])
4801			c := s.constInt32(types.Types[types.TUINT32], 1<<16)
4802			y := s.newValue2(ssa.OpOr32, types.Types[types.TUINT32], x, c)
4803			return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], y)
4804		},
4805		sys.MIPS)
4806	addF("math/bits", "TrailingZeros16",
4807		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4808			return s.newValue1(ssa.OpCtz16, types.Types[types.TINT], args[0])
4809		},
4810		sys.AMD64, sys.I386, sys.ARM, sys.ARM64, sys.Wasm)
4811	addF("math/bits", "TrailingZeros16",
4812		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4813			x := s.newValue1(ssa.OpZeroExt16to64, types.Types[types.TUINT64], args[0])
4814			c := s.constInt64(types.Types[types.TUINT64], 1<<16)
4815			y := s.newValue2(ssa.OpOr64, types.Types[types.TUINT64], x, c)
4816			return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], y)
4817		},
4818		sys.S390X, sys.PPC64)
4819	addF("math/bits", "TrailingZeros8",
4820		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4821			x := s.newValue1(ssa.OpZeroExt8to32, types.Types[types.TUINT32], args[0])
4822			c := s.constInt32(types.Types[types.TUINT32], 1<<8)
4823			y := s.newValue2(ssa.OpOr32, types.Types[types.TUINT32], x, c)
4824			return s.newValue1(ssa.OpCtz32, types.Types[types.TINT], y)
4825		},
4826		sys.MIPS)
4827	addF("math/bits", "TrailingZeros8",
4828		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4829			return s.newValue1(ssa.OpCtz8, types.Types[types.TINT], args[0])
4830		},
4831		sys.AMD64, sys.I386, sys.ARM, sys.ARM64, sys.Wasm)
4832	addF("math/bits", "TrailingZeros8",
4833		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4834			x := s.newValue1(ssa.OpZeroExt8to64, types.Types[types.TUINT64], args[0])
4835			c := s.constInt64(types.Types[types.TUINT64], 1<<8)
4836			y := s.newValue2(ssa.OpOr64, types.Types[types.TUINT64], x, c)
4837			return s.newValue1(ssa.OpCtz64, types.Types[types.TINT], y)
4838		},
4839		sys.S390X)
4840	alias("math/bits", "ReverseBytes64", "runtime/internal/sys", "Bswap64", all...)
4841	alias("math/bits", "ReverseBytes32", "runtime/internal/sys", "Bswap32", all...)
4842	// ReverseBytes inlines correctly, no need to intrinsify it.
4843	// Nothing special is needed for targets where ReverseBytes16 lowers to a rotate
4844	// On Power10, 16-bit rotate is not available so use BRH instruction
4845	if buildcfg.GOPPC64 >= 10 {
4846		addF("math/bits", "ReverseBytes16",
4847			func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4848				return s.newValue1(ssa.OpBswap16, types.Types[types.TUINT], args[0])
4849			},
4850			sys.PPC64)
4851	}
4852
4853	addF("math/bits", "Len64",
4854		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4855			return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0])
4856		},
4857		sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4858	addF("math/bits", "Len32",
4859		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4860			return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0])
4861		},
4862		sys.AMD64, sys.ARM64, sys.PPC64)
4863	addF("math/bits", "Len32",
4864		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4865			if s.config.PtrSize == 4 {
4866				return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0])
4867			}
4868			x := s.newValue1(ssa.OpZeroExt32to64, types.Types[types.TUINT64], args[0])
4869			return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x)
4870		},
4871		sys.ARM, sys.S390X, sys.MIPS, sys.Wasm)
4872	addF("math/bits", "Len16",
4873		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4874			if s.config.PtrSize == 4 {
4875				x := s.newValue1(ssa.OpZeroExt16to32, types.Types[types.TUINT32], args[0])
4876				return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], x)
4877			}
4878			x := s.newValue1(ssa.OpZeroExt16to64, types.Types[types.TUINT64], args[0])
4879			return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x)
4880		},
4881		sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4882	addF("math/bits", "Len16",
4883		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4884			return s.newValue1(ssa.OpBitLen16, types.Types[types.TINT], args[0])
4885		},
4886		sys.AMD64)
4887	addF("math/bits", "Len8",
4888		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4889			if s.config.PtrSize == 4 {
4890				x := s.newValue1(ssa.OpZeroExt8to32, types.Types[types.TUINT32], args[0])
4891				return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], x)
4892			}
4893			x := s.newValue1(ssa.OpZeroExt8to64, types.Types[types.TUINT64], args[0])
4894			return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], x)
4895		},
4896		sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4897	addF("math/bits", "Len8",
4898		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4899			return s.newValue1(ssa.OpBitLen8, types.Types[types.TINT], args[0])
4900		},
4901		sys.AMD64)
4902	addF("math/bits", "Len",
4903		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4904			if s.config.PtrSize == 4 {
4905				return s.newValue1(ssa.OpBitLen32, types.Types[types.TINT], args[0])
4906			}
4907			return s.newValue1(ssa.OpBitLen64, types.Types[types.TINT], args[0])
4908		},
4909		sys.AMD64, sys.ARM64, sys.ARM, sys.S390X, sys.MIPS, sys.PPC64, sys.Wasm)
4910	// LeadingZeros is handled because it trivially calls Len.
4911	addF("math/bits", "Reverse64",
4912		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4913			return s.newValue1(ssa.OpBitRev64, types.Types[types.TINT], args[0])
4914		},
4915		sys.ARM64)
4916	addF("math/bits", "Reverse32",
4917		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4918			return s.newValue1(ssa.OpBitRev32, types.Types[types.TINT], args[0])
4919		},
4920		sys.ARM64)
4921	addF("math/bits", "Reverse16",
4922		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4923			return s.newValue1(ssa.OpBitRev16, types.Types[types.TINT], args[0])
4924		},
4925		sys.ARM64)
4926	addF("math/bits", "Reverse8",
4927		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4928			return s.newValue1(ssa.OpBitRev8, types.Types[types.TINT], args[0])
4929		},
4930		sys.ARM64)
4931	addF("math/bits", "Reverse",
4932		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4933			return s.newValue1(ssa.OpBitRev64, types.Types[types.TINT], args[0])
4934		},
4935		sys.ARM64)
4936	addF("math/bits", "RotateLeft8",
4937		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4938			return s.newValue2(ssa.OpRotateLeft8, types.Types[types.TUINT8], args[0], args[1])
4939		},
4940		sys.AMD64, sys.RISCV64)
4941	addF("math/bits", "RotateLeft16",
4942		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4943			return s.newValue2(ssa.OpRotateLeft16, types.Types[types.TUINT16], args[0], args[1])
4944		},
4945		sys.AMD64, sys.RISCV64)
4946	addF("math/bits", "RotateLeft32",
4947		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4948			return s.newValue2(ssa.OpRotateLeft32, types.Types[types.TUINT32], args[0], args[1])
4949		},
4950		sys.AMD64, sys.ARM, sys.ARM64, sys.Loong64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm)
4951	addF("math/bits", "RotateLeft64",
4952		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4953			return s.newValue2(ssa.OpRotateLeft64, types.Types[types.TUINT64], args[0], args[1])
4954		},
4955		sys.AMD64, sys.ARM64, sys.Loong64, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm)
4956	alias("math/bits", "RotateLeft", "math/bits", "RotateLeft64", p8...)
4957
4958	makeOnesCountAMD64 := func(op ssa.Op) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4959		return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4960			if buildcfg.GOAMD64 >= 2 {
4961				return s.newValue1(op, types.Types[types.TINT], args[0])
4962			}
4963
4964			v := s.entryNewValue0A(ssa.OpHasCPUFeature, types.Types[types.TBOOL], ir.Syms.X86HasPOPCNT)
4965			b := s.endBlock()
4966			b.Kind = ssa.BlockIf
4967			b.SetControl(v)
4968			bTrue := s.f.NewBlock(ssa.BlockPlain)
4969			bFalse := s.f.NewBlock(ssa.BlockPlain)
4970			bEnd := s.f.NewBlock(ssa.BlockPlain)
4971			b.AddEdgeTo(bTrue)
4972			b.AddEdgeTo(bFalse)
4973			b.Likely = ssa.BranchLikely // most machines have popcnt nowadays
4974
4975			// We have the intrinsic - use it directly.
4976			s.startBlock(bTrue)
4977			s.vars[n] = s.newValue1(op, types.Types[types.TINT], args[0])
4978			s.endBlock().AddEdgeTo(bEnd)
4979
4980			// Call the pure Go version.
4981			s.startBlock(bFalse)
4982			s.vars[n] = s.callResult(n, callNormal) // types.Types[TINT]
4983			s.endBlock().AddEdgeTo(bEnd)
4984
4985			// Merge results.
4986			s.startBlock(bEnd)
4987			return s.variable(n, types.Types[types.TINT])
4988		}
4989	}
4990	addF("math/bits", "OnesCount64",
4991		makeOnesCountAMD64(ssa.OpPopCount64),
4992		sys.AMD64)
4993	addF("math/bits", "OnesCount64",
4994		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
4995			return s.newValue1(ssa.OpPopCount64, types.Types[types.TINT], args[0])
4996		},
4997		sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm)
4998	addF("math/bits", "OnesCount32",
4999		makeOnesCountAMD64(ssa.OpPopCount32),
5000		sys.AMD64)
5001	addF("math/bits", "OnesCount32",
5002		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5003			return s.newValue1(ssa.OpPopCount32, types.Types[types.TINT], args[0])
5004		},
5005		sys.PPC64, sys.ARM64, sys.S390X, sys.Wasm)
5006	addF("math/bits", "OnesCount16",
5007		makeOnesCountAMD64(ssa.OpPopCount16),
5008		sys.AMD64)
5009	addF("math/bits", "OnesCount16",
5010		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5011			return s.newValue1(ssa.OpPopCount16, types.Types[types.TINT], args[0])
5012		},
5013		sys.ARM64, sys.S390X, sys.PPC64, sys.Wasm)
5014	addF("math/bits", "OnesCount8",
5015		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5016			return s.newValue1(ssa.OpPopCount8, types.Types[types.TINT], args[0])
5017		},
5018		sys.S390X, sys.PPC64, sys.Wasm)
5019	addF("math/bits", "OnesCount",
5020		makeOnesCountAMD64(ssa.OpPopCount64),
5021		sys.AMD64)
5022	addF("math/bits", "Mul64",
5023		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5024			return s.newValue2(ssa.OpMul64uhilo, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1])
5025		},
5026		sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.MIPS64, sys.RISCV64, sys.Loong64)
5027	alias("math/bits", "Mul", "math/bits", "Mul64", p8...)
5028	alias("runtime/internal/math", "Mul64", "math/bits", "Mul64", p8...)
5029	addF("math/bits", "Add64",
5030		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5031			return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2])
5032		},
5033		sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.RISCV64, sys.Loong64, sys.MIPS64)
5034	alias("math/bits", "Add", "math/bits", "Add64", p8...)
5035	alias("runtime/internal/math", "Add64", "math/bits", "Add64", all...)
5036	addF("math/bits", "Sub64",
5037		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5038			return s.newValue3(ssa.OpSub64borrow, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2])
5039		},
5040		sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X, sys.RISCV64, sys.Loong64, sys.MIPS64)
5041	alias("math/bits", "Sub", "math/bits", "Sub64", p8...)
5042	addF("math/bits", "Div64",
5043		func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
5044			// check for divide-by-zero/overflow and panic with appropriate message
5045			cmpZero := s.newValue2(s.ssaOp(ir.ONE, types.Types[types.TUINT64]), types.Types[types.TBOOL], args[2], s.zeroVal(types.Types[types.TUINT64]))
5046			s.check(cmpZero, ir.Syms.Panicdivide)
5047			cmpOverflow := s.newValue2(s.ssaOp(ir.OLT, types.Types[types.TUINT64]), types.Types[types.TBOOL], args[0], args[2])
5048			s.check(cmpOverflow, ir.Syms.Panicoverflow)
5049			return s.newValue3(ssa.OpDiv128u, types.NewTuple(types.Types[types.TUINT64], types.Types[types.TUINT64]), args[0], args[1], args[2])
5050		},
5051		sys.AMD64)
5052	alias("math/bits", "Div", "math/bits", "Div64", sys.ArchAMD64)
5053
5054	alias("runtime/internal/sys", "TrailingZeros8", "math/bits", "TrailingZeros8", all...)
5055	alias("runtime/internal/sys", "TrailingZeros32", "math/bits", "TrailingZeros32", all...)
5056	alias("runtime/internal/sys", "TrailingZeros64", "math/bits", "TrailingZeros64", all...)
5057	alias("runtime/internal/sys", "Len8", "math/bits", "Len8", all...)
5058	alias("runtime/internal/sys", "Len64", "math/bits", "Len64", all...)
5059	alias("runtime/internal/sys", "OnesCount64", "math/bits", "OnesCount64", all...)
5060
5061	/******** sync/atomic ********/
5062
5063	// Note: these are disabled by flag_race in findIntrinsic below.
5064	alias("sync/atomic", "LoadInt32", "internal/runtime/atomic", "Load", all...)
5065	alias("sync/atomic", "LoadInt64", "internal/runtime/atomic", "Load64", all...)
5066	alias("sync/atomic", "LoadPointer", "internal/runtime/atomic", "Loadp", all...)
5067	alias("sync/atomic", "LoadUint32", "internal/runtime/atomic", "Load", all...)
5068	alias("sync/atomic", "LoadUint64", "internal/runtime/atomic", "Load64", all...)
5069	alias("sync/atomic", "LoadUintptr", "internal/runtime/atomic", "Load", p4...)
5070	alias("sync/atomic", "LoadUintptr", "internal/runtime/atomic", "Load64", p8...)
5071
5072	alias("sync/atomic", "StoreInt32", "internal/runtime/atomic", "Store", all...)
5073	alias("sync/atomic", "StoreInt64", "internal/runtime/atomic", "Store64", all...)
5074	// Note: not StorePointer, that needs a write barrier.  Same below for {CompareAnd}Swap.
5075	alias("sync/atomic", "StoreUint32", "internal/runtime/atomic", "Store", all...)
5076	alias("sync/atomic", "StoreUint64", "internal/runtime/atomic", "Store64", all...)
5077	alias("sync/atomic", "StoreUintptr", "internal/runtime/atomic", "Store", p4...)
5078	alias("sync/atomic", "StoreUintptr", "internal/runtime/atomic", "Store64", p8...)
5079
5080	alias("sync/atomic", "SwapInt32", "internal/runtime/atomic", "Xchg", all...)
5081	alias("sync/atomic", "SwapInt64", "internal/runtime/atomic", "Xchg64", all...)
5082	alias("sync/atomic", "SwapUint32", "internal/runtime/atomic", "Xchg", all...)
5083	alias("sync/atomic", "SwapUint64", "internal/runtime/atomic", "Xchg64", all...)
5084	alias("sync/atomic", "SwapUintptr", "internal/runtime/atomic", "Xchg", p4...)
5085	alias("sync/atomic", "SwapUintptr", "internal/runtime/atomic", "Xchg64", p8...)
5086
5087	alias("sync/atomic", "CompareAndSwapInt32", "internal/runtime/atomic", "Cas", all...)
5088	alias("sync/atomic", "CompareAndSwapInt64", "internal/runtime/atomic", "Cas64", all...)
5089	alias("sync/atomic", "CompareAndSwapUint32", "internal/runtime/atomic", "Cas", all...)
5090	alias("sync/atomic", "CompareAndSwapUint64", "internal/runtime/atomic", "Cas64", all...)
5091	alias("sync/atomic", "CompareAndSwapUintptr", "internal/runtime/atomic", "Cas", p4...)
5092	alias("sync/atomic", "CompareAndSwapUintptr", "internal/runtime/atomic", "Cas64", p8...)
5093
5094	alias("sync/atomic", "AddInt32", "internal/runtime/atomic", "Xadd", all...)
5095	alias("sync/atomic", "AddInt64", "internal/runtime/atomic", "Xadd64", all...)
5096	alias("sync/atomic", "AddUint32", "internal/runtime/atomic", "Xadd", all...)
5097	alias("sync/atomic", "AddUint64", "internal/runtime/atomic", "Xadd64", all...)
5098	alias("sync/atomic", "AddUintptr", "internal/runtime/atomic", "Xadd", p4...)
5099	alias("sync/atomic", "AddUintptr", "internal/runtime/atomic", "Xadd64", p8...)
5100
5101	alias("sync/atomic", "AndInt32", "internal/runtime/atomic", "And32", sys.ArchARM64)
5102	alias("sync/atomic", "AndUint32", "internal/runtime/atomic", "And32", sys.ArchARM64)
5103	alias("sync/atomic", "AndInt64", "internal/runtime/atomic", "And64", sys.ArchARM64)
5104	alias("sync/atomic", "AndUint64", "internal/runtime/atomic", "And64", sys.ArchARM64)
5105	alias("sync/atomic", "AndUintptr", "internal/runtime/atomic", "And64", sys.ArchARM64)
5106	alias("sync/atomic", "OrInt32", "internal/runtime/atomic", "Or32", sys.ArchARM64)
5107	alias("sync/atomic", "OrUint32", "internal/runtime/atomic", "Or32", sys.ArchARM64)
5108	alias("sync/atomic", "OrInt64", "internal/runtime/atomic", "Or64", sys.ArchARM64)
5109	alias("sync/atomic", "OrUint64", "internal/runtime/atomic", "Or64", sys.ArchARM64)
5110	alias("sync/atomic", "OrUintptr", "internal/runtime/atomic", "Or64", sys.ArchARM64)
5111
5112	/******** math/big ********/
5113	alias("math/big", "mulWW", "math/bits", "Mul64", p8...)
5114}
5115
5116// findIntrinsic returns a function which builds the SSA equivalent of the
5117// function identified by the symbol sym.  If sym is not an intrinsic call, returns nil.
5118func findIntrinsic(sym *types.Sym) intrinsicBuilder {
5119	if sym == nil || sym.Pkg == nil {
5120		return nil
5121	}
5122	pkg := sym.Pkg.Path
5123	if sym.Pkg == ir.Pkgs.Runtime {
5124		pkg = "runtime"
5125	}
5126	if base.Flag.Race && pkg == "sync/atomic" {
5127		// The race detector needs to be able to intercept these calls.
5128		// We can't intrinsify them.
5129		return nil
5130	}
5131	// Skip intrinsifying math functions (which may contain hard-float
5132	// instructions) when soft-float
5133	if Arch.SoftFloat && pkg == "math" {
5134		return nil
5135	}
5136
5137	fn := sym.Name
5138	if ssa.IntrinsicsDisable {
5139		if pkg == "runtime" && (fn == "getcallerpc" || fn == "getcallersp" || fn == "getclosureptr") {
5140			// These runtime functions don't have definitions, must be intrinsics.
5141		} else {
5142			return nil
5143		}
5144	}
5145	return intrinsics[intrinsicKey{Arch.LinkArch.Arch, pkg, fn}]
5146}
5147
5148func IsIntrinsicCall(n *ir.CallExpr) bool {
5149	if n == nil {
5150		return false
5151	}
5152	name, ok := n.Fun.(*ir.Name)
5153	if !ok {
5154		return false
5155	}
5156	return findIntrinsic(name.Sym()) != nil
5157}
5158
5159// intrinsicCall converts a call to a recognized intrinsic function into the intrinsic SSA operation.
5160func (s *state) intrinsicCall(n *ir.CallExpr) *ssa.Value {
5161	v := findIntrinsic(n.Fun.Sym())(s, n, s.intrinsicArgs(n))
5162	if ssa.IntrinsicsDebug > 0 {
5163		x := v
5164		if x == nil {
5165			x = s.mem()
5166		}
5167		if x.Op == ssa.OpSelect0 || x.Op == ssa.OpSelect1 {
5168			x = x.Args[0]
5169		}
5170		base.WarnfAt(n.Pos(), "intrinsic substitution for %v with %s", n.Fun.Sym().Name, x.LongString())
5171	}
5172	return v
5173}
5174
5175// intrinsicArgs extracts args from n, evaluates them to SSA values, and returns them.
5176func (s *state) intrinsicArgs(n *ir.CallExpr) []*ssa.Value {
5177	args := make([]*ssa.Value, len(n.Args))
5178	for i, n := range n.Args {
5179		args[i] = s.expr(n)
5180	}
5181	return args
5182}
5183
5184// openDeferRecord adds code to evaluate and store the function for an open-code defer
5185// call, and records info about the defer, so we can generate proper code on the
5186// exit paths. n is the sub-node of the defer node that is the actual function
5187// call. We will also record funcdata information on where the function is stored
5188// (as well as the deferBits variable), and this will enable us to run the proper
5189// defer calls during panics.
5190func (s *state) openDeferRecord(n *ir.CallExpr) {
5191	if len(n.Args) != 0 || n.Op() != ir.OCALLFUNC || n.Fun.Type().NumResults() != 0 {
5192		s.Fatalf("defer call with arguments or results: %v", n)
5193	}
5194
5195	opendefer := &openDeferInfo{
5196		n: n,
5197	}
5198	fn := n.Fun
5199	// We must always store the function value in a stack slot for the
5200	// runtime panic code to use. But in the defer exit code, we will
5201	// call the function directly if it is a static function.
5202	closureVal := s.expr(fn)
5203	closure := s.openDeferSave(fn.Type(), closureVal)
5204	opendefer.closureNode = closure.Aux.(*ir.Name)
5205	if !(fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC) {
5206		opendefer.closure = closure
5207	}
5208	index := len(s.openDefers)
5209	s.openDefers = append(s.openDefers, opendefer)
5210
5211	// Update deferBits only after evaluation and storage to stack of
5212	// the function is successful.
5213	bitvalue := s.constInt8(types.Types[types.TUINT8], 1<<uint(index))
5214	newDeferBits := s.newValue2(ssa.OpOr8, types.Types[types.TUINT8], s.variable(deferBitsVar, types.Types[types.TUINT8]), bitvalue)
5215	s.vars[deferBitsVar] = newDeferBits
5216	s.store(types.Types[types.TUINT8], s.deferBitsAddr, newDeferBits)
5217}
5218
5219// openDeferSave generates SSA nodes to store a value (with type t) for an
5220// open-coded defer at an explicit autotmp location on the stack, so it can be
5221// reloaded and used for the appropriate call on exit. Type t must be a function type
5222// (therefore SSAable). val is the value to be stored. The function returns an SSA
5223// value representing a pointer to the autotmp location.
5224func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value {
5225	if !ssa.CanSSA(t) {
5226		s.Fatalf("openDeferSave of non-SSA-able type %v val=%v", t, val)
5227	}
5228	if !t.HasPointers() {
5229		s.Fatalf("openDeferSave of pointerless type %v val=%v", t, val)
5230	}
5231	pos := val.Pos
5232	temp := typecheck.TempAt(pos.WithNotStmt(), s.curfn, t)
5233	temp.SetOpenDeferSlot(true)
5234	temp.SetFrameOffset(int64(len(s.openDefers))) // so cmpstackvarlt can order them
5235	var addrTemp *ssa.Value
5236	// Use OpVarLive to make sure stack slot for the closure is not removed by
5237	// dead-store elimination
5238	if s.curBlock.ID != s.f.Entry.ID {
5239		// Force the tmp storing this defer function to be declared in the entry
5240		// block, so that it will be live for the defer exit code (which will
5241		// actually access it only if the associated defer call has been activated).
5242		if t.HasPointers() {
5243			s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
5244		}
5245		s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
5246		addrTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.defvars[s.f.Entry.ID][memVar])
5247	} else {
5248		// Special case if we're still in the entry block. We can't use
5249		// the above code, since s.defvars[s.f.Entry.ID] isn't defined
5250		// until we end the entry block with s.endBlock().
5251		if t.HasPointers() {
5252			s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, temp, s.mem(), false)
5253		}
5254		s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, temp, s.mem(), false)
5255		addrTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.mem(), false)
5256	}
5257	// Since we may use this temp during exit depending on the
5258	// deferBits, we must define it unconditionally on entry.
5259	// Therefore, we must make sure it is zeroed out in the entry
5260	// block if it contains pointers, else GC may wrongly follow an
5261	// uninitialized pointer value.
5262	temp.SetNeedzero(true)
5263	// We are storing to the stack, hence we can avoid the full checks in
5264	// storeType() (no write barrier) and do a simple store().
5265	s.store(t, addrTemp, val)
5266	return addrTemp
5267}
5268
5269// openDeferExit generates SSA for processing all the open coded defers at exit.
5270// The code involves loading deferBits, and checking each of the bits to see if
5271// the corresponding defer statement was executed. For each bit that is turned
5272// on, the associated defer call is made.
5273func (s *state) openDeferExit() {
5274	deferExit := s.f.NewBlock(ssa.BlockPlain)
5275	s.endBlock().AddEdgeTo(deferExit)
5276	s.startBlock(deferExit)
5277	s.lastDeferExit = deferExit
5278	s.lastDeferCount = len(s.openDefers)
5279	zeroval := s.constInt8(types.Types[types.TUINT8], 0)
5280	// Test for and run defers in reverse order
5281	for i := len(s.openDefers) - 1; i >= 0; i-- {
5282		r := s.openDefers[i]
5283		bCond := s.f.NewBlock(ssa.BlockPlain)
5284		bEnd := s.f.NewBlock(ssa.BlockPlain)
5285
5286		deferBits := s.variable(deferBitsVar, types.Types[types.TUINT8])
5287		// Generate code to check if the bit associated with the current
5288		// defer is set.
5289		bitval := s.constInt8(types.Types[types.TUINT8], 1<<uint(i))
5290		andval := s.newValue2(ssa.OpAnd8, types.Types[types.TUINT8], deferBits, bitval)
5291		eqVal := s.newValue2(ssa.OpEq8, types.Types[types.TBOOL], andval, zeroval)
5292		b := s.endBlock()
5293		b.Kind = ssa.BlockIf
5294		b.SetControl(eqVal)
5295		b.AddEdgeTo(bEnd)
5296		b.AddEdgeTo(bCond)
5297		bCond.AddEdgeTo(bEnd)
5298		s.startBlock(bCond)
5299
5300		// Clear this bit in deferBits and force store back to stack, so
5301		// we will not try to re-run this defer call if this defer call panics.
5302		nbitval := s.newValue1(ssa.OpCom8, types.Types[types.TUINT8], bitval)
5303		maskedval := s.newValue2(ssa.OpAnd8, types.Types[types.TUINT8], deferBits, nbitval)
5304		s.store(types.Types[types.TUINT8], s.deferBitsAddr, maskedval)
5305		// Use this value for following tests, so we keep previous
5306		// bits cleared.
5307		s.vars[deferBitsVar] = maskedval
5308
5309		// Generate code to call the function call of the defer, using the
5310		// closure that were stored in argtmps at the point of the defer
5311		// statement.
5312		fn := r.n.Fun
5313		stksize := fn.Type().ArgWidth()
5314		var callArgs []*ssa.Value
5315		var call *ssa.Value
5316		if r.closure != nil {
5317			v := s.load(r.closure.Type.Elem(), r.closure)
5318			s.maybeNilCheckClosure(v, callDefer)
5319			codeptr := s.rawLoad(types.Types[types.TUINTPTR], v)
5320			aux := ssa.ClosureAuxCall(s.f.ABIDefault.ABIAnalyzeTypes(nil, nil))
5321			call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, v)
5322		} else {
5323			aux := ssa.StaticAuxCall(fn.(*ir.Name).Linksym(), s.f.ABIDefault.ABIAnalyzeTypes(nil, nil))
5324			call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
5325		}
5326		callArgs = append(callArgs, s.mem())
5327		call.AddArgs(callArgs...)
5328		call.AuxInt = stksize
5329		s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, 0, call)
5330		// Make sure that the stack slots with pointers are kept live
5331		// through the call (which is a pre-emption point). Also, we will
5332		// use the first call of the last defer exit to compute liveness
5333		// for the deferreturn, so we want all stack slots to be live.
5334		if r.closureNode != nil {
5335			s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, r.closureNode, s.mem(), false)
5336		}
5337
5338		s.endBlock()
5339		s.startBlock(bEnd)
5340	}
5341}
5342
5343func (s *state) callResult(n *ir.CallExpr, k callKind) *ssa.Value {
5344	return s.call(n, k, false, nil)
5345}
5346
5347func (s *state) callAddr(n *ir.CallExpr, k callKind) *ssa.Value {
5348	return s.call(n, k, true, nil)
5349}
5350
5351// Calls the function n using the specified call type.
5352// Returns the address of the return value (or nil if none).
5353func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExtra ir.Expr) *ssa.Value {
5354	s.prevCall = nil
5355	var calleeLSym *obj.LSym // target function (if static)
5356	var closure *ssa.Value   // ptr to closure to run (if dynamic)
5357	var codeptr *ssa.Value   // ptr to target code (if dynamic)
5358	var dextra *ssa.Value    // defer extra arg
5359	var rcvr *ssa.Value      // receiver to set
5360	fn := n.Fun
5361	var ACArgs []*types.Type    // AuxCall args
5362	var ACResults []*types.Type // AuxCall results
5363	var callArgs []*ssa.Value   // For late-expansion, the args themselves (not stored, args to the call instead).
5364
5365	callABI := s.f.ABIDefault
5366
5367	if k != callNormal && k != callTail && (len(n.Args) != 0 || n.Op() == ir.OCALLINTER || n.Fun.Type().NumResults() != 0) {
5368		s.Fatalf("go/defer call with arguments: %v", n)
5369	}
5370
5371	switch n.Op() {
5372	case ir.OCALLFUNC:
5373		if (k == callNormal || k == callTail) && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
5374			fn := fn.(*ir.Name)
5375			calleeLSym = callTargetLSym(fn)
5376			if buildcfg.Experiment.RegabiArgs {
5377				// This is a static call, so it may be
5378				// a direct call to a non-ABIInternal
5379				// function. fn.Func may be nil for
5380				// some compiler-generated functions,
5381				// but those are all ABIInternal.
5382				if fn.Func != nil {
5383					callABI = abiForFunc(fn.Func, s.f.ABI0, s.f.ABI1)
5384				}
5385			} else {
5386				// TODO(register args) remove after register abi is working
5387				inRegistersImported := fn.Pragma()&ir.RegisterParams != 0
5388				inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0
5389				if inRegistersImported || inRegistersSamePackage {
5390					callABI = s.f.ABI1
5391				}
5392			}
5393			break
5394		}
5395		closure = s.expr(fn)
5396		if k != callDefer && k != callDeferStack {
5397			// Deferred nil function needs to panic when the function is invoked,
5398			// not the point of defer statement.
5399			s.maybeNilCheckClosure(closure, k)
5400		}
5401	case ir.OCALLINTER:
5402		if fn.Op() != ir.ODOTINTER {
5403			s.Fatalf("OCALLINTER: n.Left not an ODOTINTER: %v", fn.Op())
5404		}
5405		fn := fn.(*ir.SelectorExpr)
5406		var iclosure *ssa.Value
5407		iclosure, rcvr = s.getClosureAndRcvr(fn)
5408		if k == callNormal {
5409			codeptr = s.load(types.Types[types.TUINTPTR], iclosure)
5410		} else {
5411			closure = iclosure
5412		}
5413	}
5414	if deferExtra != nil {
5415		dextra = s.expr(deferExtra)
5416	}
5417
5418	params := callABI.ABIAnalyze(n.Fun.Type(), false /* Do not set (register) nNames from caller side -- can cause races. */)
5419	types.CalcSize(fn.Type())
5420	stksize := params.ArgWidth() // includes receiver, args, and results
5421
5422	res := n.Fun.Type().Results()
5423	if k == callNormal || k == callTail {
5424		for _, p := range params.OutParams() {
5425			ACResults = append(ACResults, p.Type)
5426		}
5427	}
5428
5429	var call *ssa.Value
5430	if k == callDeferStack {
5431		if stksize != 0 {
5432			s.Fatalf("deferprocStack with non-zero stack size %d: %v", stksize, n)
5433		}
5434		// Make a defer struct on the stack.
5435		t := deferstruct()
5436		n, addr := s.temp(n.Pos(), t)
5437		n.SetNonMergeable(true)
5438		s.store(closure.Type,
5439			s.newValue1I(ssa.OpOffPtr, closure.Type.PtrTo(), t.FieldOff(deferStructFnField), addr),
5440			closure)
5441
5442		// Call runtime.deferprocStack with pointer to _defer record.
5443		ACArgs = append(ACArgs, types.Types[types.TUINTPTR])
5444		aux := ssa.StaticAuxCall(ir.Syms.DeferprocStack, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults))
5445		callArgs = append(callArgs, addr, s.mem())
5446		call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
5447		call.AddArgs(callArgs...)
5448		call.AuxInt = int64(types.PtrSize) // deferprocStack takes a *_defer arg
5449	} else {
5450		// Store arguments to stack, including defer/go arguments and receiver for method calls.
5451		// These are written in SP-offset order.
5452		argStart := base.Ctxt.Arch.FixedFrameSize
5453		// Defer/go args.
5454		if k != callNormal && k != callTail {
5455			// Write closure (arg to newproc/deferproc).
5456			ACArgs = append(ACArgs, types.Types[types.TUINTPTR]) // not argExtra
5457			callArgs = append(callArgs, closure)
5458			stksize += int64(types.PtrSize)
5459			argStart += int64(types.PtrSize)
5460			if dextra != nil {
5461				// Extra token of type any for deferproc
5462				ACArgs = append(ACArgs, types.Types[types.TINTER])
5463				callArgs = append(callArgs, dextra)
5464				stksize += 2 * int64(types.PtrSize)
5465				argStart += 2 * int64(types.PtrSize)
5466			}
5467		}
5468
5469		// Set receiver (for interface calls).
5470		if rcvr != nil {
5471			callArgs = append(callArgs, rcvr)
5472		}
5473
5474		// Write args.
5475		t := n.Fun.Type()
5476		args := n.Args
5477
5478		for _, p := range params.InParams() { // includes receiver for interface calls
5479			ACArgs = append(ACArgs, p.Type)
5480		}
5481
5482		// Split the entry block if there are open defers, because later calls to
5483		// openDeferSave may cause a mismatch between the mem for an OpDereference
5484		// and the call site which uses it. See #49282.
5485		if s.curBlock.ID == s.f.Entry.ID && s.hasOpenDefers {
5486			b := s.endBlock()
5487			b.Kind = ssa.BlockPlain
5488			curb := s.f.NewBlock(ssa.BlockPlain)
5489			b.AddEdgeTo(curb)
5490			s.startBlock(curb)
5491		}
5492
5493		for i, n := range args {
5494			callArgs = append(callArgs, s.putArg(n, t.Param(i).Type))
5495		}
5496
5497		callArgs = append(callArgs, s.mem())
5498
5499		// call target
5500		switch {
5501		case k == callDefer:
5502			sym := ir.Syms.Deferproc
5503			if dextra != nil {
5504				sym = ir.Syms.Deferprocat
5505			}
5506			aux := ssa.StaticAuxCall(sym, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults)) // TODO paramResultInfo for Deferproc(at)
5507			call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
5508		case k == callGo:
5509			aux := ssa.StaticAuxCall(ir.Syms.Newproc, s.f.ABIDefault.ABIAnalyzeTypes(ACArgs, ACResults))
5510			call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux) // TODO paramResultInfo for Newproc
5511		case closure != nil:
5512			// rawLoad because loading the code pointer from a
5513			// closure is always safe, but IsSanitizerSafeAddr
5514			// can't always figure that out currently, and it's
5515			// critical that we not clobber any arguments already
5516			// stored onto the stack.
5517			codeptr = s.rawLoad(types.Types[types.TUINTPTR], closure)
5518			aux := ssa.ClosureAuxCall(callABI.ABIAnalyzeTypes(ACArgs, ACResults))
5519			call = s.newValue2A(ssa.OpClosureLECall, aux.LateExpansionResultType(), aux, codeptr, closure)
5520		case codeptr != nil:
5521			// Note that the "receiver" parameter is nil because the actual receiver is the first input parameter.
5522			aux := ssa.InterfaceAuxCall(params)
5523			call = s.newValue1A(ssa.OpInterLECall, aux.LateExpansionResultType(), aux, codeptr)
5524		case calleeLSym != nil:
5525			aux := ssa.StaticAuxCall(calleeLSym, params)
5526			call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
5527			if k == callTail {
5528				call.Op = ssa.OpTailLECall
5529				stksize = 0 // Tail call does not use stack. We reuse caller's frame.
5530			}
5531		default:
5532			s.Fatalf("bad call type %v %v", n.Op(), n)
5533		}
5534		call.AddArgs(callArgs...)
5535		call.AuxInt = stksize // Call operations carry the argsize of the callee along with them
5536	}
5537	s.prevCall = call
5538	s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(ACResults)), call)
5539	// Insert VarLive opcodes.
5540	for _, v := range n.KeepAlive {
5541		if !v.Addrtaken() {
5542			s.Fatalf("KeepAlive variable %v must have Addrtaken set", v)
5543		}
5544		switch v.Class {
5545		case ir.PAUTO, ir.PPARAM, ir.PPARAMOUT:
5546		default:
5547			s.Fatalf("KeepAlive variable %v must be Auto or Arg", v)
5548		}
5549		s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, v, s.mem())
5550	}
5551
5552	// Finish block for defers
5553	if k == callDefer || k == callDeferStack {
5554		b := s.endBlock()
5555		b.Kind = ssa.BlockDefer
5556		b.SetControl(call)
5557		bNext := s.f.NewBlock(ssa.BlockPlain)
5558		b.AddEdgeTo(bNext)
5559		// Add recover edge to exit code.
5560		r := s.f.NewBlock(ssa.BlockPlain)
5561		s.startBlock(r)
5562		s.exit()
5563		b.AddEdgeTo(r)
5564		b.Likely = ssa.BranchLikely
5565		s.startBlock(bNext)
5566	}
5567
5568	if len(res) == 0 || k != callNormal {
5569		// call has no return value. Continue with the next statement.
5570		return nil
5571	}
5572	fp := res[0]
5573	if returnResultAddr {
5574		return s.resultAddrOfCall(call, 0, fp.Type)
5575	}
5576	return s.newValue1I(ssa.OpSelectN, fp.Type, 0, call)
5577}
5578
5579// maybeNilCheckClosure checks if a nil check of a closure is needed in some
5580// architecture-dependent situations and, if so, emits the nil check.
5581func (s *state) maybeNilCheckClosure(closure *ssa.Value, k callKind) {
5582	if Arch.LinkArch.Family == sys.Wasm || buildcfg.GOOS == "aix" && k != callGo {
5583		// On AIX, the closure needs to be verified as fn can be nil, except if it's a call go. This needs to be handled by the runtime to have the "go of nil func value" error.
5584		// TODO(neelance): On other architectures this should be eliminated by the optimization steps
5585		s.nilCheck(closure)
5586	}
5587}
5588
5589// getClosureAndRcvr returns values for the appropriate closure and receiver of an
5590// interface call
5591func (s *state) getClosureAndRcvr(fn *ir.SelectorExpr) (*ssa.Value, *ssa.Value) {
5592	i := s.expr(fn.X)
5593	itab := s.newValue1(ssa.OpITab, types.Types[types.TUINTPTR], i)
5594	s.nilCheck(itab)
5595	itabidx := fn.Offset() + rttype.ITab.OffsetOf("Fun")
5596	closure := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.UintptrPtr, itabidx, itab)
5597	rcvr := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, i)
5598	return closure, rcvr
5599}
5600
5601// etypesign returns the signed-ness of e, for integer/pointer etypes.
5602// -1 means signed, +1 means unsigned, 0 means non-integer/non-pointer.
5603func etypesign(e types.Kind) int8 {
5604	switch e {
5605	case types.TINT8, types.TINT16, types.TINT32, types.TINT64, types.TINT:
5606		return -1
5607	case types.TUINT8, types.TUINT16, types.TUINT32, types.TUINT64, types.TUINT, types.TUINTPTR, types.TUNSAFEPTR:
5608		return +1
5609	}
5610	return 0
5611}
5612
5613// addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
5614// The value that the returned Value represents is guaranteed to be non-nil.
5615func (s *state) addr(n ir.Node) *ssa.Value {
5616	if n.Op() != ir.ONAME {
5617		s.pushLine(n.Pos())
5618		defer s.popLine()
5619	}
5620
5621	if s.canSSA(n) {
5622		s.Fatalf("addr of canSSA expression: %+v", n)
5623	}
5624
5625	t := types.NewPtr(n.Type())
5626	linksymOffset := func(lsym *obj.LSym, offset int64) *ssa.Value {
5627		v := s.entryNewValue1A(ssa.OpAddr, t, lsym, s.sb)
5628		// TODO: Make OpAddr use AuxInt as well as Aux.
5629		if offset != 0 {
5630			v = s.entryNewValue1I(ssa.OpOffPtr, v.Type, offset, v)
5631		}
5632		return v
5633	}
5634	switch n.Op() {
5635	case ir.OLINKSYMOFFSET:
5636		no := n.(*ir.LinksymOffsetExpr)
5637		return linksymOffset(no.Linksym, no.Offset_)
5638	case ir.ONAME:
5639		n := n.(*ir.Name)
5640		if n.Heapaddr != nil {
5641			return s.expr(n.Heapaddr)
5642		}
5643		switch n.Class {
5644		case ir.PEXTERN:
5645			// global variable
5646			return linksymOffset(n.Linksym(), 0)
5647		case ir.PPARAM:
5648			// parameter slot
5649			v := s.decladdrs[n]
5650			if v != nil {
5651				return v
5652			}
5653			s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
5654			return nil
5655		case ir.PAUTO:
5656			return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), !ir.IsAutoTmp(n))
5657
5658		case ir.PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
5659			// ensure that we reuse symbols for out parameters so
5660			// that cse works on their addresses
5661			return s.newValue2Apos(ssa.OpLocalAddr, t, n, s.sp, s.mem(), true)
5662		default:
5663			s.Fatalf("variable address class %v not implemented", n.Class)
5664			return nil
5665		}
5666	case ir.ORESULT:
5667		// load return from callee
5668		n := n.(*ir.ResultExpr)
5669		return s.resultAddrOfCall(s.prevCall, n.Index, n.Type())
5670	case ir.OINDEX:
5671		n := n.(*ir.IndexExpr)
5672		if n.X.Type().IsSlice() {
5673			a := s.expr(n.X)
5674			i := s.expr(n.Index)
5675			len := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], a)
5676			i = s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded())
5677			p := s.newValue1(ssa.OpSlicePtr, t, a)
5678			return s.newValue2(ssa.OpPtrIndex, t, p, i)
5679		} else { // array
5680			a := s.addr(n.X)
5681			i := s.expr(n.Index)
5682			len := s.constInt(types.Types[types.TINT], n.X.Type().NumElem())
5683			i = s.boundsCheck(i, len, ssa.BoundsIndex, n.Bounded())
5684			return s.newValue2(ssa.OpPtrIndex, types.NewPtr(n.X.Type().Elem()), a, i)
5685		}
5686	case ir.ODEREF:
5687		n := n.(*ir.StarExpr)
5688		return s.exprPtr(n.X, n.Bounded(), n.Pos())
5689	case ir.ODOT:
5690		n := n.(*ir.SelectorExpr)
5691		p := s.addr(n.X)
5692		return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
5693	case ir.ODOTPTR:
5694		n := n.(*ir.SelectorExpr)
5695		p := s.exprPtr(n.X, n.Bounded(), n.Pos())
5696		return s.newValue1I(ssa.OpOffPtr, t, n.Offset(), p)
5697	case ir.OCONVNOP:
5698		n := n.(*ir.ConvExpr)
5699		if n.Type() == n.X.Type() {
5700			return s.addr(n.X)
5701		}
5702		addr := s.addr(n.X)
5703		return s.newValue1(ssa.OpCopy, t, addr) // ensure that addr has the right type
5704	case ir.OCALLFUNC, ir.OCALLINTER:
5705		n := n.(*ir.CallExpr)
5706		return s.callAddr(n, callNormal)
5707	case ir.ODOTTYPE, ir.ODYNAMICDOTTYPE:
5708		var v *ssa.Value
5709		if n.Op() == ir.ODOTTYPE {
5710			v, _ = s.dottype(n.(*ir.TypeAssertExpr), false)
5711		} else {
5712			v, _ = s.dynamicDottype(n.(*ir.DynamicTypeAssertExpr), false)
5713		}
5714		if v.Op != ssa.OpLoad {
5715			s.Fatalf("dottype of non-load")
5716		}
5717		if v.Args[1] != s.mem() {
5718			s.Fatalf("memory no longer live from dottype load")
5719		}
5720		return v.Args[0]
5721	default:
5722		s.Fatalf("unhandled addr %v", n.Op())
5723		return nil
5724	}
5725}
5726
5727// canSSA reports whether n is SSA-able.
5728// n must be an ONAME (or an ODOT sequence with an ONAME base).
5729func (s *state) canSSA(n ir.Node) bool {
5730	if base.Flag.N != 0 {
5731		return false
5732	}
5733	for {
5734		nn := n
5735		if nn.Op() == ir.ODOT {
5736			nn := nn.(*ir.SelectorExpr)
5737			n = nn.X
5738			continue
5739		}
5740		if nn.Op() == ir.OINDEX {
5741			nn := nn.(*ir.IndexExpr)
5742			if nn.X.Type().IsArray() {
5743				n = nn.X
5744				continue
5745			}
5746		}
5747		break
5748	}
5749	if n.Op() != ir.ONAME {
5750		return false
5751	}
5752	return s.canSSAName(n.(*ir.Name)) && ssa.CanSSA(n.Type())
5753}
5754
5755func (s *state) canSSAName(name *ir.Name) bool {
5756	if name.Addrtaken() || !name.OnStack() {
5757		return false
5758	}
5759	switch name.Class {
5760	case ir.PPARAMOUT:
5761		if s.hasdefer {
5762			// TODO: handle this case? Named return values must be
5763			// in memory so that the deferred function can see them.
5764			// Maybe do: if !strings.HasPrefix(n.String(), "~") { return false }
5765			// Or maybe not, see issue 18860.  Even unnamed return values
5766			// must be written back so if a defer recovers, the caller can see them.
5767			return false
5768		}
5769		if s.cgoUnsafeArgs {
5770			// Cgo effectively takes the address of all result args,
5771			// but the compiler can't see that.
5772			return false
5773		}
5774	}
5775	return true
5776	// TODO: try to make more variables SSAable?
5777}
5778
5779// exprPtr evaluates n to a pointer and nil-checks it.
5780func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value {
5781	p := s.expr(n)
5782	if bounded || n.NonNil() {
5783		if s.f.Frontend().Debug_checknil() && lineno.Line() > 1 {
5784			s.f.Warnl(lineno, "removed nil check")
5785		}
5786		return p
5787	}
5788	p = s.nilCheck(p)
5789	return p
5790}
5791
5792// nilCheck generates nil pointer checking code.
5793// Used only for automatically inserted nil checks,
5794// not for user code like 'x != nil'.
5795// Returns a "definitely not nil" copy of x to ensure proper ordering
5796// of the uses of the post-nilcheck pointer.
5797func (s *state) nilCheck(ptr *ssa.Value) *ssa.Value {
5798	if base.Debug.DisableNil != 0 || s.curfn.NilCheckDisabled() {
5799		return ptr
5800	}
5801	return s.newValue2(ssa.OpNilCheck, ptr.Type, ptr, s.mem())
5802}
5803
5804// boundsCheck generates bounds checking code. Checks if 0 <= idx <[=] len, branches to exit if not.
5805// Starts a new block on return.
5806// On input, len must be converted to full int width and be nonnegative.
5807// Returns idx converted to full int width.
5808// If bounded is true then caller guarantees the index is not out of bounds
5809// (but boundsCheck will still extend the index to full int width).
5810func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
5811	idx = s.extendIndex(idx, len, kind, bounded)
5812
5813	if bounded || base.Flag.B != 0 {
5814		// If bounded or bounds checking is flag-disabled, then no check necessary,
5815		// just return the extended index.
5816		//
5817		// Here, bounded == true if the compiler generated the index itself,
5818		// such as in the expansion of a slice initializer. These indexes are
5819		// compiler-generated, not Go program variables, so they cannot be
5820		// attacker-controlled, so we can omit Spectre masking as well.
5821		//
5822		// Note that we do not want to omit Spectre masking in code like:
5823		//
5824		//	if 0 <= i && i < len(x) {
5825		//		use(x[i])
5826		//	}
5827		//
5828		// Lucky for us, bounded==false for that code.
5829		// In that case (handled below), we emit a bound check (and Spectre mask)
5830		// and then the prove pass will remove the bounds check.
5831		// In theory the prove pass could potentially remove certain
5832		// Spectre masks, but it's very delicate and probably better
5833		// to be conservative and leave them all in.
5834		return idx
5835	}
5836
5837	bNext := s.f.NewBlock(ssa.BlockPlain)
5838	bPanic := s.f.NewBlock(ssa.BlockExit)
5839
5840	if !idx.Type.IsSigned() {
5841		switch kind {
5842		case ssa.BoundsIndex:
5843			kind = ssa.BoundsIndexU
5844		case ssa.BoundsSliceAlen:
5845			kind = ssa.BoundsSliceAlenU
5846		case ssa.BoundsSliceAcap:
5847			kind = ssa.BoundsSliceAcapU
5848		case ssa.BoundsSliceB:
5849			kind = ssa.BoundsSliceBU
5850		case ssa.BoundsSlice3Alen:
5851			kind = ssa.BoundsSlice3AlenU
5852		case ssa.BoundsSlice3Acap:
5853			kind = ssa.BoundsSlice3AcapU
5854		case ssa.BoundsSlice3B:
5855			kind = ssa.BoundsSlice3BU
5856		case ssa.BoundsSlice3C:
5857			kind = ssa.BoundsSlice3CU
5858		}
5859	}
5860
5861	var cmp *ssa.Value
5862	if kind == ssa.BoundsIndex || kind == ssa.BoundsIndexU {
5863		cmp = s.newValue2(ssa.OpIsInBounds, types.Types[types.TBOOL], idx, len)
5864	} else {
5865		cmp = s.newValue2(ssa.OpIsSliceInBounds, types.Types[types.TBOOL], idx, len)
5866	}
5867	b := s.endBlock()
5868	b.Kind = ssa.BlockIf
5869	b.SetControl(cmp)
5870	b.Likely = ssa.BranchLikely
5871	b.AddEdgeTo(bNext)
5872	b.AddEdgeTo(bPanic)
5873
5874	s.startBlock(bPanic)
5875	if Arch.LinkArch.Family == sys.Wasm {
5876		// TODO(khr): figure out how to do "register" based calling convention for bounds checks.
5877		// Should be similar to gcWriteBarrier, but I can't make it work.
5878		s.rtcall(BoundsCheckFunc[kind], false, nil, idx, len)
5879	} else {
5880		mem := s.newValue3I(ssa.OpPanicBounds, types.TypeMem, int64(kind), idx, len, s.mem())
5881		s.endBlock().SetControl(mem)
5882	}
5883	s.startBlock(bNext)
5884
5885	// In Spectre index mode, apply an appropriate mask to avoid speculative out-of-bounds accesses.
5886	if base.Flag.Cfg.SpectreIndex {
5887		op := ssa.OpSpectreIndex
5888		if kind != ssa.BoundsIndex && kind != ssa.BoundsIndexU {
5889			op = ssa.OpSpectreSliceIndex
5890		}
5891		idx = s.newValue2(op, types.Types[types.TINT], idx, len)
5892	}
5893
5894	return idx
5895}
5896
5897// If cmp (a bool) is false, panic using the given function.
5898func (s *state) check(cmp *ssa.Value, fn *obj.LSym) {
5899	b := s.endBlock()
5900	b.Kind = ssa.BlockIf
5901	b.SetControl(cmp)
5902	b.Likely = ssa.BranchLikely
5903	bNext := s.f.NewBlock(ssa.BlockPlain)
5904	line := s.peekPos()
5905	pos := base.Ctxt.PosTable.Pos(line)
5906	fl := funcLine{f: fn, base: pos.Base(), line: pos.Line()}
5907	bPanic := s.panics[fl]
5908	if bPanic == nil {
5909		bPanic = s.f.NewBlock(ssa.BlockPlain)
5910		s.panics[fl] = bPanic
5911		s.startBlock(bPanic)
5912		// The panic call takes/returns memory to ensure that the right
5913		// memory state is observed if the panic happens.
5914		s.rtcall(fn, false, nil)
5915	}
5916	b.AddEdgeTo(bNext)
5917	b.AddEdgeTo(bPanic)
5918	s.startBlock(bNext)
5919}
5920
5921func (s *state) intDivide(n ir.Node, a, b *ssa.Value) *ssa.Value {
5922	needcheck := true
5923	switch b.Op {
5924	case ssa.OpConst8, ssa.OpConst16, ssa.OpConst32, ssa.OpConst64:
5925		if b.AuxInt != 0 {
5926			needcheck = false
5927		}
5928	}
5929	if needcheck {
5930		// do a size-appropriate check for zero
5931		cmp := s.newValue2(s.ssaOp(ir.ONE, n.Type()), types.Types[types.TBOOL], b, s.zeroVal(n.Type()))
5932		s.check(cmp, ir.Syms.Panicdivide)
5933	}
5934	return s.newValue2(s.ssaOp(n.Op(), n.Type()), a.Type, a, b)
5935}
5936
5937// rtcall issues a call to the given runtime function fn with the listed args.
5938// Returns a slice of results of the given result types.
5939// The call is added to the end of the current block.
5940// If returns is false, the block is marked as an exit block.
5941func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args ...*ssa.Value) []*ssa.Value {
5942	s.prevCall = nil
5943	// Write args to the stack
5944	off := base.Ctxt.Arch.FixedFrameSize
5945	var callArgs []*ssa.Value
5946	var callArgTypes []*types.Type
5947
5948	for _, arg := range args {
5949		t := arg.Type
5950		off = types.RoundUp(off, t.Alignment())
5951		size := t.Size()
5952		callArgs = append(callArgs, arg)
5953		callArgTypes = append(callArgTypes, t)
5954		off += size
5955	}
5956	off = types.RoundUp(off, int64(types.RegSize))
5957
5958	// Issue call
5959	var call *ssa.Value
5960	aux := ssa.StaticAuxCall(fn, s.f.ABIDefault.ABIAnalyzeTypes(callArgTypes, results))
5961	callArgs = append(callArgs, s.mem())
5962	call = s.newValue0A(ssa.OpStaticLECall, aux.LateExpansionResultType(), aux)
5963	call.AddArgs(callArgs...)
5964	s.vars[memVar] = s.newValue1I(ssa.OpSelectN, types.TypeMem, int64(len(results)), call)
5965
5966	if !returns {
5967		// Finish block
5968		b := s.endBlock()
5969		b.Kind = ssa.BlockExit
5970		b.SetControl(call)
5971		call.AuxInt = off - base.Ctxt.Arch.FixedFrameSize
5972		if len(results) > 0 {
5973			s.Fatalf("panic call can't have results")
5974		}
5975		return nil
5976	}
5977
5978	// Load results
5979	res := make([]*ssa.Value, len(results))
5980	for i, t := range results {
5981		off = types.RoundUp(off, t.Alignment())
5982		res[i] = s.resultOfCall(call, int64(i), t)
5983		off += t.Size()
5984	}
5985	off = types.RoundUp(off, int64(types.PtrSize))
5986
5987	// Remember how much callee stack space we needed.
5988	call.AuxInt = off
5989
5990	return res
5991}
5992
5993// do *left = right for type t.
5994func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask, leftIsStmt bool) {
5995	s.instrument(t, left, instrumentWrite)
5996
5997	if skip == 0 && (!t.HasPointers() || ssa.IsStackAddr(left)) {
5998		// Known to not have write barrier. Store the whole type.
5999		s.vars[memVar] = s.newValue3Apos(ssa.OpStore, types.TypeMem, t, left, right, s.mem(), leftIsStmt)
6000		return
6001	}
6002
6003	// store scalar fields first, so write barrier stores for
6004	// pointer fields can be grouped together, and scalar values
6005	// don't need to be live across the write barrier call.
6006	// TODO: if the writebarrier pass knows how to reorder stores,
6007	// we can do a single store here as long as skip==0.
6008	s.storeTypeScalars(t, left, right, skip)
6009	if skip&skipPtr == 0 && t.HasPointers() {
6010		s.storeTypePtrs(t, left, right)
6011	}
6012}
6013
6014// do *left = right for all scalar (non-pointer) parts of t.
6015func (s *state) storeTypeScalars(t *types.Type, left, right *ssa.Value, skip skipMask) {
6016	switch {
6017	case t.IsBoolean() || t.IsInteger() || t.IsFloat() || t.IsComplex():
6018		s.store(t, left, right)
6019	case t.IsPtrShaped():
6020		if t.IsPtr() && t.Elem().NotInHeap() {
6021			s.store(t, left, right) // see issue 42032
6022		}
6023		// otherwise, no scalar fields.
6024	case t.IsString():
6025		if skip&skipLen != 0 {
6026			return
6027		}
6028		len := s.newValue1(ssa.OpStringLen, types.Types[types.TINT], right)
6029		lenAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, s.config.PtrSize, left)
6030		s.store(types.Types[types.TINT], lenAddr, len)
6031	case t.IsSlice():
6032		if skip&skipLen == 0 {
6033			len := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], right)
6034			lenAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, s.config.PtrSize, left)
6035			s.store(types.Types[types.TINT], lenAddr, len)
6036		}
6037		if skip&skipCap == 0 {
6038			cap := s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], right)
6039			capAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.IntPtr, 2*s.config.PtrSize, left)
6040			s.store(types.Types[types.TINT], capAddr, cap)
6041		}
6042	case t.IsInterface():
6043		// itab field doesn't need a write barrier (even though it is a pointer).
6044		itab := s.newValue1(ssa.OpITab, s.f.Config.Types.BytePtr, right)
6045		s.store(types.Types[types.TUINTPTR], left, itab)
6046	case t.IsStruct():
6047		n := t.NumFields()
6048		for i := 0; i < n; i++ {
6049			ft := t.FieldType(i)
6050			addr := s.newValue1I(ssa.OpOffPtr, ft.PtrTo(), t.FieldOff(i), left)
6051			val := s.newValue1I(ssa.OpStructSelect, ft, int64(i), right)
6052			s.storeTypeScalars(ft, addr, val, 0)
6053		}
6054	case t.IsArray() && t.NumElem() == 0:
6055		// nothing
6056	case t.IsArray() && t.NumElem() == 1:
6057		s.storeTypeScalars(t.Elem(), left, s.newValue1I(ssa.OpArraySelect, t.Elem(), 0, right), 0)
6058	default:
6059		s.Fatalf("bad write barrier type %v", t)
6060	}
6061}
6062
6063// do *left = right for all pointer parts of t.
6064func (s *state) storeTypePtrs(t *types.Type, left, right *ssa.Value) {
6065	switch {
6066	case t.IsPtrShaped():
6067		if t.IsPtr() && t.Elem().NotInHeap() {
6068			break // see issue 42032
6069		}
6070		s.store(t, left, right)
6071	case t.IsString():
6072		ptr := s.newValue1(ssa.OpStringPtr, s.f.Config.Types.BytePtr, right)
6073		s.store(s.f.Config.Types.BytePtr, left, ptr)
6074	case t.IsSlice():
6075		elType := types.NewPtr(t.Elem())
6076		ptr := s.newValue1(ssa.OpSlicePtr, elType, right)
6077		s.store(elType, left, ptr)
6078	case t.IsInterface():
6079		// itab field is treated as a scalar.
6080		idata := s.newValue1(ssa.OpIData, s.f.Config.Types.BytePtr, right)
6081		idataAddr := s.newValue1I(ssa.OpOffPtr, s.f.Config.Types.BytePtrPtr, s.config.PtrSize, left)
6082		s.store(s.f.Config.Types.BytePtr, idataAddr, idata)
6083	case t.IsStruct():
6084		n := t.NumFields()
6085		for i := 0; i < n; i++ {
6086			ft := t.FieldType(i)
6087			if !ft.HasPointers() {
6088				continue
6089			}
6090			addr := s.newValue1I(ssa.OpOffPtr, ft.PtrTo(), t.FieldOff(i), left)
6091			val := s.newValue1I(ssa.OpStructSelect, ft, int64(i), right)
6092			s.storeTypePtrs(ft, addr, val)
6093		}
6094	case t.IsArray() && t.NumElem() == 0:
6095		// nothing
6096	case t.IsArray() && t.NumElem() == 1:
6097		s.storeTypePtrs(t.Elem(), left, s.newValue1I(ssa.OpArraySelect, t.Elem(), 0, right))
6098	default:
6099		s.Fatalf("bad write barrier type %v", t)
6100	}
6101}
6102
6103// putArg evaluates n for the purpose of passing it as an argument to a function and returns the value for the call.
6104func (s *state) putArg(n ir.Node, t *types.Type) *ssa.Value {
6105	var a *ssa.Value
6106	if !ssa.CanSSA(t) {
6107		a = s.newValue2(ssa.OpDereference, t, s.addr(n), s.mem())
6108	} else {
6109		a = s.expr(n)
6110	}
6111	return a
6112}
6113
6114func (s *state) storeArgWithBase(n ir.Node, t *types.Type, base *ssa.Value, off int64) {
6115	pt := types.NewPtr(t)
6116	var addr *ssa.Value
6117	if base == s.sp {
6118		// Use special routine that avoids allocation on duplicate offsets.
6119		addr = s.constOffPtrSP(pt, off)
6120	} else {
6121		addr = s.newValue1I(ssa.OpOffPtr, pt, off, base)
6122	}
6123
6124	if !ssa.CanSSA(t) {
6125		a := s.addr(n)
6126		s.move(t, addr, a)
6127		return
6128	}
6129
6130	a := s.expr(n)
6131	s.storeType(t, addr, a, 0, false)
6132}
6133
6134// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
6135// i,j,k may be nil, in which case they are set to their default value.
6136// v may be a slice, string or pointer to an array.
6137func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) {
6138	t := v.Type
6139	var ptr, len, cap *ssa.Value
6140	switch {
6141	case t.IsSlice():
6142		ptr = s.newValue1(ssa.OpSlicePtr, types.NewPtr(t.Elem()), v)
6143		len = s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v)
6144		cap = s.newValue1(ssa.OpSliceCap, types.Types[types.TINT], v)
6145	case t.IsString():
6146		ptr = s.newValue1(ssa.OpStringPtr, types.NewPtr(types.Types[types.TUINT8]), v)
6147		len = s.newValue1(ssa.OpStringLen, types.Types[types.TINT], v)
6148		cap = len
6149	case t.IsPtr():
6150		if !t.Elem().IsArray() {
6151			s.Fatalf("bad ptr to array in slice %v\n", t)
6152		}
6153		nv := s.nilCheck(v)
6154		ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), nv)
6155		len = s.constInt(types.Types[types.TINT], t.Elem().NumElem())
6156		cap = len
6157	default:
6158		s.Fatalf("bad type in slice %v\n", t)
6159	}
6160
6161	// Set default values
6162	if i == nil {
6163		i = s.constInt(types.Types[types.TINT], 0)
6164	}
6165	if j == nil {
6166		j = len
6167	}
6168	three := true
6169	if k == nil {
6170		three = false
6171		k = cap
6172	}
6173
6174	// Panic if slice indices are not in bounds.
6175	// Make sure we check these in reverse order so that we're always
6176	// comparing against a value known to be nonnegative. See issue 28797.
6177	if three {
6178		if k != cap {
6179			kind := ssa.BoundsSlice3Alen
6180			if t.IsSlice() {
6181				kind = ssa.BoundsSlice3Acap
6182			}
6183			k = s.boundsCheck(k, cap, kind, bounded)
6184		}
6185		if j != k {
6186			j = s.boundsCheck(j, k, ssa.BoundsSlice3B, bounded)
6187		}
6188		i = s.boundsCheck(i, j, ssa.BoundsSlice3C, bounded)
6189	} else {
6190		if j != k {
6191			kind := ssa.BoundsSliceAlen
6192			if t.IsSlice() {
6193				kind = ssa.BoundsSliceAcap
6194			}
6195			j = s.boundsCheck(j, k, kind, bounded)
6196		}
6197		i = s.boundsCheck(i, j, ssa.BoundsSliceB, bounded)
6198	}
6199
6200	// Word-sized integer operations.
6201	subOp := s.ssaOp(ir.OSUB, types.Types[types.TINT])
6202	mulOp := s.ssaOp(ir.OMUL, types.Types[types.TINT])
6203	andOp := s.ssaOp(ir.OAND, types.Types[types.TINT])
6204
6205	// Calculate the length (rlen) and capacity (rcap) of the new slice.
6206	// For strings the capacity of the result is unimportant. However,
6207	// we use rcap to test if we've generated a zero-length slice.
6208	// Use length of strings for that.
6209	rlen := s.newValue2(subOp, types.Types[types.TINT], j, i)
6210	rcap := rlen
6211	if j != k && !t.IsString() {
6212		rcap = s.newValue2(subOp, types.Types[types.TINT], k, i)
6213	}
6214
6215	if (i.Op == ssa.OpConst64 || i.Op == ssa.OpConst32) && i.AuxInt == 0 {
6216		// No pointer arithmetic necessary.
6217		return ptr, rlen, rcap
6218	}
6219
6220	// Calculate the base pointer (rptr) for the new slice.
6221	//
6222	// Generate the following code assuming that indexes are in bounds.
6223	// The masking is to make sure that we don't generate a slice
6224	// that points to the next object in memory. We cannot just set
6225	// the pointer to nil because then we would create a nil slice or
6226	// string.
6227	//
6228	//     rcap = k - i
6229	//     rlen = j - i
6230	//     rptr = ptr + (mask(rcap) & (i * stride))
6231	//
6232	// Where mask(x) is 0 if x==0 and -1 if x>0 and stride is the width
6233	// of the element type.
6234	stride := s.constInt(types.Types[types.TINT], ptr.Type.Elem().Size())
6235
6236	// The delta is the number of bytes to offset ptr by.
6237	delta := s.newValue2(mulOp, types.Types[types.TINT], i, stride)
6238
6239	// If we're slicing to the point where the capacity is zero,
6240	// zero out the delta.
6241	mask := s.newValue1(ssa.OpSlicemask, types.Types[types.TINT], rcap)
6242	delta = s.newValue2(andOp, types.Types[types.TINT], delta, mask)
6243
6244	// Compute rptr = ptr + delta.
6245	rptr := s.newValue2(ssa.OpAddPtr, ptr.Type, ptr, delta)
6246
6247	return rptr, rlen, rcap
6248}
6249
6250type u642fcvtTab struct {
6251	leq, cvt2F, and, rsh, or, add ssa.Op
6252	one                           func(*state, *types.Type, int64) *ssa.Value
6253}
6254
6255var u64_f64 = u642fcvtTab{
6256	leq:   ssa.OpLeq64,
6257	cvt2F: ssa.OpCvt64to64F,
6258	and:   ssa.OpAnd64,
6259	rsh:   ssa.OpRsh64Ux64,
6260	or:    ssa.OpOr64,
6261	add:   ssa.OpAdd64F,
6262	one:   (*state).constInt64,
6263}
6264
6265var u64_f32 = u642fcvtTab{
6266	leq:   ssa.OpLeq64,
6267	cvt2F: ssa.OpCvt64to32F,
6268	and:   ssa.OpAnd64,
6269	rsh:   ssa.OpRsh64Ux64,
6270	or:    ssa.OpOr64,
6271	add:   ssa.OpAdd32F,
6272	one:   (*state).constInt64,
6273}
6274
6275func (s *state) uint64Tofloat64(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6276	return s.uint64Tofloat(&u64_f64, n, x, ft, tt)
6277}
6278
6279func (s *state) uint64Tofloat32(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6280	return s.uint64Tofloat(&u64_f32, n, x, ft, tt)
6281}
6282
6283func (s *state) uint64Tofloat(cvttab *u642fcvtTab, n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6284	// if x >= 0 {
6285	//    result = (floatY) x
6286	// } else {
6287	// 	  y = uintX(x) ; y = x & 1
6288	// 	  z = uintX(x) ; z = z >> 1
6289	// 	  z = z | y
6290	// 	  result = floatY(z)
6291	// 	  result = result + result
6292	// }
6293	//
6294	// Code borrowed from old code generator.
6295	// What's going on: large 64-bit "unsigned" looks like
6296	// negative number to hardware's integer-to-float
6297	// conversion. However, because the mantissa is only
6298	// 63 bits, we don't need the LSB, so instead we do an
6299	// unsigned right shift (divide by two), convert, and
6300	// double. However, before we do that, we need to be
6301	// sure that we do not lose a "1" if that made the
6302	// difference in the resulting rounding. Therefore, we
6303	// preserve it, and OR (not ADD) it back in. The case
6304	// that matters is when the eleven discarded bits are
6305	// equal to 10000000001; that rounds up, and the 1 cannot
6306	// be lost else it would round down if the LSB of the
6307	// candidate mantissa is 0.
6308	cmp := s.newValue2(cvttab.leq, types.Types[types.TBOOL], s.zeroVal(ft), x)
6309	b := s.endBlock()
6310	b.Kind = ssa.BlockIf
6311	b.SetControl(cmp)
6312	b.Likely = ssa.BranchLikely
6313
6314	bThen := s.f.NewBlock(ssa.BlockPlain)
6315	bElse := s.f.NewBlock(ssa.BlockPlain)
6316	bAfter := s.f.NewBlock(ssa.BlockPlain)
6317
6318	b.AddEdgeTo(bThen)
6319	s.startBlock(bThen)
6320	a0 := s.newValue1(cvttab.cvt2F, tt, x)
6321	s.vars[n] = a0
6322	s.endBlock()
6323	bThen.AddEdgeTo(bAfter)
6324
6325	b.AddEdgeTo(bElse)
6326	s.startBlock(bElse)
6327	one := cvttab.one(s, ft, 1)
6328	y := s.newValue2(cvttab.and, ft, x, one)
6329	z := s.newValue2(cvttab.rsh, ft, x, one)
6330	z = s.newValue2(cvttab.or, ft, z, y)
6331	a := s.newValue1(cvttab.cvt2F, tt, z)
6332	a1 := s.newValue2(cvttab.add, tt, a, a)
6333	s.vars[n] = a1
6334	s.endBlock()
6335	bElse.AddEdgeTo(bAfter)
6336
6337	s.startBlock(bAfter)
6338	return s.variable(n, n.Type())
6339}
6340
6341type u322fcvtTab struct {
6342	cvtI2F, cvtF2F ssa.Op
6343}
6344
6345var u32_f64 = u322fcvtTab{
6346	cvtI2F: ssa.OpCvt32to64F,
6347	cvtF2F: ssa.OpCopy,
6348}
6349
6350var u32_f32 = u322fcvtTab{
6351	cvtI2F: ssa.OpCvt32to32F,
6352	cvtF2F: ssa.OpCvt64Fto32F,
6353}
6354
6355func (s *state) uint32Tofloat64(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6356	return s.uint32Tofloat(&u32_f64, n, x, ft, tt)
6357}
6358
6359func (s *state) uint32Tofloat32(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6360	return s.uint32Tofloat(&u32_f32, n, x, ft, tt)
6361}
6362
6363func (s *state) uint32Tofloat(cvttab *u322fcvtTab, n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6364	// if x >= 0 {
6365	// 	result = floatY(x)
6366	// } else {
6367	// 	result = floatY(float64(x) + (1<<32))
6368	// }
6369	cmp := s.newValue2(ssa.OpLeq32, types.Types[types.TBOOL], s.zeroVal(ft), x)
6370	b := s.endBlock()
6371	b.Kind = ssa.BlockIf
6372	b.SetControl(cmp)
6373	b.Likely = ssa.BranchLikely
6374
6375	bThen := s.f.NewBlock(ssa.BlockPlain)
6376	bElse := s.f.NewBlock(ssa.BlockPlain)
6377	bAfter := s.f.NewBlock(ssa.BlockPlain)
6378
6379	b.AddEdgeTo(bThen)
6380	s.startBlock(bThen)
6381	a0 := s.newValue1(cvttab.cvtI2F, tt, x)
6382	s.vars[n] = a0
6383	s.endBlock()
6384	bThen.AddEdgeTo(bAfter)
6385
6386	b.AddEdgeTo(bElse)
6387	s.startBlock(bElse)
6388	a1 := s.newValue1(ssa.OpCvt32to64F, types.Types[types.TFLOAT64], x)
6389	twoToThe32 := s.constFloat64(types.Types[types.TFLOAT64], float64(1<<32))
6390	a2 := s.newValue2(ssa.OpAdd64F, types.Types[types.TFLOAT64], a1, twoToThe32)
6391	a3 := s.newValue1(cvttab.cvtF2F, tt, a2)
6392
6393	s.vars[n] = a3
6394	s.endBlock()
6395	bElse.AddEdgeTo(bAfter)
6396
6397	s.startBlock(bAfter)
6398	return s.variable(n, n.Type())
6399}
6400
6401// referenceTypeBuiltin generates code for the len/cap builtins for maps and channels.
6402func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
6403	if !n.X.Type().IsMap() && !n.X.Type().IsChan() {
6404		s.Fatalf("node must be a map or a channel")
6405	}
6406	if n.X.Type().IsChan() && n.Op() == ir.OLEN {
6407		s.Fatalf("cannot inline len(chan)") // must use runtime.chanlen now
6408	}
6409	if n.X.Type().IsChan() && n.Op() == ir.OCAP {
6410		s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now
6411	}
6412	// if n == nil {
6413	//   return 0
6414	// } else {
6415	//   // len
6416	//   return *((*int)n)
6417	//   // cap
6418	//   return *(((*int)n)+1)
6419	// }
6420	lenType := n.Type()
6421	nilValue := s.constNil(types.Types[types.TUINTPTR])
6422	cmp := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], x, nilValue)
6423	b := s.endBlock()
6424	b.Kind = ssa.BlockIf
6425	b.SetControl(cmp)
6426	b.Likely = ssa.BranchUnlikely
6427
6428	bThen := s.f.NewBlock(ssa.BlockPlain)
6429	bElse := s.f.NewBlock(ssa.BlockPlain)
6430	bAfter := s.f.NewBlock(ssa.BlockPlain)
6431
6432	// length/capacity of a nil map/chan is zero
6433	b.AddEdgeTo(bThen)
6434	s.startBlock(bThen)
6435	s.vars[n] = s.zeroVal(lenType)
6436	s.endBlock()
6437	bThen.AddEdgeTo(bAfter)
6438
6439	b.AddEdgeTo(bElse)
6440	s.startBlock(bElse)
6441	switch n.Op() {
6442	case ir.OLEN:
6443		// length is stored in the first word for map/chan
6444		s.vars[n] = s.load(lenType, x)
6445	case ir.OCAP:
6446		// capacity is stored in the second word for chan
6447		sw := s.newValue1I(ssa.OpOffPtr, lenType.PtrTo(), lenType.Size(), x)
6448		s.vars[n] = s.load(lenType, sw)
6449	default:
6450		s.Fatalf("op must be OLEN or OCAP")
6451	}
6452	s.endBlock()
6453	bElse.AddEdgeTo(bAfter)
6454
6455	s.startBlock(bAfter)
6456	return s.variable(n, lenType)
6457}
6458
6459type f2uCvtTab struct {
6460	ltf, cvt2U, subf, or ssa.Op
6461	floatValue           func(*state, *types.Type, float64) *ssa.Value
6462	intValue             func(*state, *types.Type, int64) *ssa.Value
6463	cutoff               uint64
6464}
6465
6466var f32_u64 = f2uCvtTab{
6467	ltf:        ssa.OpLess32F,
6468	cvt2U:      ssa.OpCvt32Fto64,
6469	subf:       ssa.OpSub32F,
6470	or:         ssa.OpOr64,
6471	floatValue: (*state).constFloat32,
6472	intValue:   (*state).constInt64,
6473	cutoff:     1 << 63,
6474}
6475
6476var f64_u64 = f2uCvtTab{
6477	ltf:        ssa.OpLess64F,
6478	cvt2U:      ssa.OpCvt64Fto64,
6479	subf:       ssa.OpSub64F,
6480	or:         ssa.OpOr64,
6481	floatValue: (*state).constFloat64,
6482	intValue:   (*state).constInt64,
6483	cutoff:     1 << 63,
6484}
6485
6486var f32_u32 = f2uCvtTab{
6487	ltf:        ssa.OpLess32F,
6488	cvt2U:      ssa.OpCvt32Fto32,
6489	subf:       ssa.OpSub32F,
6490	or:         ssa.OpOr32,
6491	floatValue: (*state).constFloat32,
6492	intValue:   func(s *state, t *types.Type, v int64) *ssa.Value { return s.constInt32(t, int32(v)) },
6493	cutoff:     1 << 31,
6494}
6495
6496var f64_u32 = f2uCvtTab{
6497	ltf:        ssa.OpLess64F,
6498	cvt2U:      ssa.OpCvt64Fto32,
6499	subf:       ssa.OpSub64F,
6500	or:         ssa.OpOr32,
6501	floatValue: (*state).constFloat64,
6502	intValue:   func(s *state, t *types.Type, v int64) *ssa.Value { return s.constInt32(t, int32(v)) },
6503	cutoff:     1 << 31,
6504}
6505
6506func (s *state) float32ToUint64(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6507	return s.floatToUint(&f32_u64, n, x, ft, tt)
6508}
6509func (s *state) float64ToUint64(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6510	return s.floatToUint(&f64_u64, n, x, ft, tt)
6511}
6512
6513func (s *state) float32ToUint32(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6514	return s.floatToUint(&f32_u32, n, x, ft, tt)
6515}
6516
6517func (s *state) float64ToUint32(n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6518	return s.floatToUint(&f64_u32, n, x, ft, tt)
6519}
6520
6521func (s *state) floatToUint(cvttab *f2uCvtTab, n ir.Node, x *ssa.Value, ft, tt *types.Type) *ssa.Value {
6522	// cutoff:=1<<(intY_Size-1)
6523	// if x < floatX(cutoff) {
6524	// 	result = uintY(x)
6525	// } else {
6526	// 	y = x - floatX(cutoff)
6527	// 	z = uintY(y)
6528	// 	result = z | -(cutoff)
6529	// }
6530	cutoff := cvttab.floatValue(s, ft, float64(cvttab.cutoff))
6531	cmp := s.newValue2(cvttab.ltf, types.Types[types.TBOOL], x, cutoff)
6532	b := s.endBlock()
6533	b.Kind = ssa.BlockIf
6534	b.SetControl(cmp)
6535	b.Likely = ssa.BranchLikely
6536
6537	bThen := s.f.NewBlock(ssa.BlockPlain)
6538	bElse := s.f.NewBlock(ssa.BlockPlain)
6539	bAfter := s.f.NewBlock(ssa.BlockPlain)
6540
6541	b.AddEdgeTo(bThen)
6542	s.startBlock(bThen)
6543	a0 := s.newValue1(cvttab.cvt2U, tt, x)
6544	s.vars[n] = a0
6545	s.endBlock()
6546	bThen.AddEdgeTo(bAfter)
6547
6548	b.AddEdgeTo(bElse)
6549	s.startBlock(bElse)
6550	y := s.newValue2(cvttab.subf, ft, x, cutoff)
6551	y = s.newValue1(cvttab.cvt2U, tt, y)
6552	z := cvttab.intValue(s, tt, int64(-cvttab.cutoff))
6553	a1 := s.newValue2(cvttab.or, tt, y, z)
6554	s.vars[n] = a1
6555	s.endBlock()
6556	bElse.AddEdgeTo(bAfter)
6557
6558	s.startBlock(bAfter)
6559	return s.variable(n, n.Type())
6560}
6561
6562// dottype generates SSA for a type assertion node.
6563// commaok indicates whether to panic or return a bool.
6564// If commaok is false, resok will be nil.
6565func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Value) {
6566	iface := s.expr(n.X)              // input interface
6567	target := s.reflectType(n.Type()) // target type
6568	var targetItab *ssa.Value
6569	if n.ITab != nil {
6570		targetItab = s.expr(n.ITab)
6571	}
6572	return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, nil, target, targetItab, commaok, n.Descriptor)
6573}
6574
6575func (s *state) dynamicDottype(n *ir.DynamicTypeAssertExpr, commaok bool) (res, resok *ssa.Value) {
6576	iface := s.expr(n.X)
6577	var source, target, targetItab *ssa.Value
6578	if n.SrcRType != nil {
6579		source = s.expr(n.SrcRType)
6580	}
6581	if !n.X.Type().IsEmptyInterface() && !n.Type().IsInterface() {
6582		byteptr := s.f.Config.Types.BytePtr
6583		targetItab = s.expr(n.ITab)
6584		// TODO(mdempsky): Investigate whether compiling n.RType could be
6585		// better than loading itab.typ.
6586		target = s.load(byteptr, s.newValue1I(ssa.OpOffPtr, byteptr, rttype.ITab.OffsetOf("Type"), targetItab))
6587	} else {
6588		target = s.expr(n.RType)
6589	}
6590	return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, source, target, targetItab, commaok, nil)
6591}
6592
6593// dottype1 implements a x.(T) operation. iface is the argument (x), dst is the type we're asserting to (T)
6594// and src is the type we're asserting from.
6595// source is the *runtime._type of src
6596// target is the *runtime._type of dst.
6597// If src is a nonempty interface and dst is not an interface, targetItab is an itab representing (dst, src). Otherwise it is nil.
6598// commaok is true if the caller wants a boolean success value. Otherwise, the generated code panics if the conversion fails.
6599// descriptor is a compiler-allocated internal/abi.TypeAssert whose address is passed to runtime.typeAssert when
6600// the target type is a compile-time-known non-empty interface. It may be nil.
6601func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, source, target, targetItab *ssa.Value, commaok bool, descriptor *obj.LSym) (res, resok *ssa.Value) {
6602	typs := s.f.Config.Types
6603	byteptr := typs.BytePtr
6604	if dst.IsInterface() {
6605		if dst.IsEmptyInterface() {
6606			// Converting to an empty interface.
6607			// Input could be an empty or nonempty interface.
6608			if base.Debug.TypeAssert > 0 {
6609				base.WarnfAt(pos, "type assertion inlined")
6610			}
6611
6612			// Get itab/type field from input.
6613			itab := s.newValue1(ssa.OpITab, byteptr, iface)
6614			// Conversion succeeds iff that field is not nil.
6615			cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], itab, s.constNil(byteptr))
6616
6617			if src.IsEmptyInterface() && commaok {
6618				// Converting empty interface to empty interface with ,ok is just a nil check.
6619				return iface, cond
6620			}
6621
6622			// Branch on nilness.
6623			b := s.endBlock()
6624			b.Kind = ssa.BlockIf
6625			b.SetControl(cond)
6626			b.Likely = ssa.BranchLikely
6627			bOk := s.f.NewBlock(ssa.BlockPlain)
6628			bFail := s.f.NewBlock(ssa.BlockPlain)
6629			b.AddEdgeTo(bOk)
6630			b.AddEdgeTo(bFail)
6631
6632			if !commaok {
6633				// On failure, panic by calling panicnildottype.
6634				s.startBlock(bFail)
6635				s.rtcall(ir.Syms.Panicnildottype, false, nil, target)
6636
6637				// On success, return (perhaps modified) input interface.
6638				s.startBlock(bOk)
6639				if src.IsEmptyInterface() {
6640					res = iface // Use input interface unchanged.
6641					return
6642				}
6643				// Load type out of itab, build interface with existing idata.
6644				off := s.newValue1I(ssa.OpOffPtr, byteptr, rttype.ITab.OffsetOf("Type"), itab)
6645				typ := s.load(byteptr, off)
6646				idata := s.newValue1(ssa.OpIData, byteptr, iface)
6647				res = s.newValue2(ssa.OpIMake, dst, typ, idata)
6648				return
6649			}
6650
6651			s.startBlock(bOk)
6652			// nonempty -> empty
6653			// Need to load type from itab
6654			off := s.newValue1I(ssa.OpOffPtr, byteptr, rttype.ITab.OffsetOf("Type"), itab)
6655			s.vars[typVar] = s.load(byteptr, off)
6656			s.endBlock()
6657
6658			// itab is nil, might as well use that as the nil result.
6659			s.startBlock(bFail)
6660			s.vars[typVar] = itab
6661			s.endBlock()
6662
6663			// Merge point.
6664			bEnd := s.f.NewBlock(ssa.BlockPlain)
6665			bOk.AddEdgeTo(bEnd)
6666			bFail.AddEdgeTo(bEnd)
6667			s.startBlock(bEnd)
6668			idata := s.newValue1(ssa.OpIData, byteptr, iface)
6669			res = s.newValue2(ssa.OpIMake, dst, s.variable(typVar, byteptr), idata)
6670			resok = cond
6671			delete(s.vars, typVar) // no practical effect, just to indicate typVar is no longer live.
6672			return
6673		}
6674		// converting to a nonempty interface needs a runtime call.
6675		if base.Debug.TypeAssert > 0 {
6676			base.WarnfAt(pos, "type assertion not inlined")
6677		}
6678
6679		itab := s.newValue1(ssa.OpITab, byteptr, iface)
6680		data := s.newValue1(ssa.OpIData, types.Types[types.TUNSAFEPTR], iface)
6681
6682		// First, check for nil.
6683		bNil := s.f.NewBlock(ssa.BlockPlain)
6684		bNonNil := s.f.NewBlock(ssa.BlockPlain)
6685		bMerge := s.f.NewBlock(ssa.BlockPlain)
6686		cond := s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], itab, s.constNil(byteptr))
6687		b := s.endBlock()
6688		b.Kind = ssa.BlockIf
6689		b.SetControl(cond)
6690		b.Likely = ssa.BranchLikely
6691		b.AddEdgeTo(bNonNil)
6692		b.AddEdgeTo(bNil)
6693
6694		s.startBlock(bNil)
6695		if commaok {
6696			s.vars[typVar] = itab // which will be nil
6697			b := s.endBlock()
6698			b.AddEdgeTo(bMerge)
6699		} else {
6700			// Panic if input is nil.
6701			s.rtcall(ir.Syms.Panicnildottype, false, nil, target)
6702		}
6703
6704		// Get typ, possibly by loading out of itab.
6705		s.startBlock(bNonNil)
6706		typ := itab
6707		if !src.IsEmptyInterface() {
6708			typ = s.load(byteptr, s.newValue1I(ssa.OpOffPtr, byteptr, rttype.ITab.OffsetOf("Type"), itab))
6709		}
6710
6711		// Check the cache first.
6712		var d *ssa.Value
6713		if descriptor != nil {
6714			d = s.newValue1A(ssa.OpAddr, byteptr, descriptor, s.sb)
6715			if base.Flag.N == 0 && rtabi.UseInterfaceSwitchCache(Arch.LinkArch.Name) {
6716				// Note: we can only use the cache if we have the right atomic load instruction.
6717				// Double-check that here.
6718				if _, ok := intrinsics[intrinsicKey{Arch.LinkArch.Arch, "internal/runtime/atomic", "Loadp"}]; !ok {
6719					s.Fatalf("atomic load not available")
6720				}
6721				// Pick right size ops.
6722				var mul, and, add, zext ssa.Op
6723				if s.config.PtrSize == 4 {
6724					mul = ssa.OpMul32
6725					and = ssa.OpAnd32
6726					add = ssa.OpAdd32
6727					zext = ssa.OpCopy
6728				} else {
6729					mul = ssa.OpMul64
6730					and = ssa.OpAnd64
6731					add = ssa.OpAdd64
6732					zext = ssa.OpZeroExt32to64
6733				}
6734
6735				loopHead := s.f.NewBlock(ssa.BlockPlain)
6736				loopBody := s.f.NewBlock(ssa.BlockPlain)
6737				cacheHit := s.f.NewBlock(ssa.BlockPlain)
6738				cacheMiss := s.f.NewBlock(ssa.BlockPlain)
6739
6740				// Load cache pointer out of descriptor, with an atomic load so
6741				// we ensure that we see a fully written cache.
6742				atomicLoad := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(typs.BytePtr, types.TypeMem), d, s.mem())
6743				cache := s.newValue1(ssa.OpSelect0, typs.BytePtr, atomicLoad)
6744				s.vars[memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, atomicLoad)
6745
6746				// Load hash from type or itab.
6747				var hash *ssa.Value
6748				if src.IsEmptyInterface() {
6749					hash = s.newValue2(ssa.OpLoad, typs.UInt32, s.newValue1I(ssa.OpOffPtr, typs.UInt32Ptr, rttype.Type.OffsetOf("Hash"), typ), s.mem())
6750				} else {
6751					hash = s.newValue2(ssa.OpLoad, typs.UInt32, s.newValue1I(ssa.OpOffPtr, typs.UInt32Ptr, rttype.ITab.OffsetOf("Hash"), itab), s.mem())
6752				}
6753				hash = s.newValue1(zext, typs.Uintptr, hash)
6754				s.vars[hashVar] = hash
6755				// Load mask from cache.
6756				mask := s.newValue2(ssa.OpLoad, typs.Uintptr, cache, s.mem())
6757				// Jump to loop head.
6758				b := s.endBlock()
6759				b.AddEdgeTo(loopHead)
6760
6761				// At loop head, get pointer to the cache entry.
6762				//   e := &cache.Entries[hash&mask]
6763				s.startBlock(loopHead)
6764				idx := s.newValue2(and, typs.Uintptr, s.variable(hashVar, typs.Uintptr), mask)
6765				idx = s.newValue2(mul, typs.Uintptr, idx, s.uintptrConstant(uint64(2*s.config.PtrSize)))
6766				idx = s.newValue2(add, typs.Uintptr, idx, s.uintptrConstant(uint64(s.config.PtrSize)))
6767				e := s.newValue2(ssa.OpAddPtr, typs.UintptrPtr, cache, idx)
6768				//   hash++
6769				s.vars[hashVar] = s.newValue2(add, typs.Uintptr, s.variable(hashVar, typs.Uintptr), s.uintptrConstant(1))
6770
6771				// Look for a cache hit.
6772				//   if e.Typ == typ { goto hit }
6773				eTyp := s.newValue2(ssa.OpLoad, typs.Uintptr, e, s.mem())
6774				cmp1 := s.newValue2(ssa.OpEqPtr, typs.Bool, typ, eTyp)
6775				b = s.endBlock()
6776				b.Kind = ssa.BlockIf
6777				b.SetControl(cmp1)
6778				b.AddEdgeTo(cacheHit)
6779				b.AddEdgeTo(loopBody)
6780
6781				// Look for an empty entry, the tombstone for this hash table.
6782				//   if e.Typ == nil { goto miss }
6783				s.startBlock(loopBody)
6784				cmp2 := s.newValue2(ssa.OpEqPtr, typs.Bool, eTyp, s.constNil(typs.BytePtr))
6785				b = s.endBlock()
6786				b.Kind = ssa.BlockIf
6787				b.SetControl(cmp2)
6788				b.AddEdgeTo(cacheMiss)
6789				b.AddEdgeTo(loopHead)
6790
6791				// On a hit, load the data fields of the cache entry.
6792				//   Itab = e.Itab
6793				s.startBlock(cacheHit)
6794				eItab := s.newValue2(ssa.OpLoad, typs.BytePtr, s.newValue1I(ssa.OpOffPtr, typs.BytePtrPtr, s.config.PtrSize, e), s.mem())
6795				s.vars[typVar] = eItab
6796				b = s.endBlock()
6797				b.AddEdgeTo(bMerge)
6798
6799				// On a miss, call into the runtime to get the answer.
6800				s.startBlock(cacheMiss)
6801			}
6802		}
6803
6804		// Call into runtime to get itab for result.
6805		if descriptor != nil {
6806			itab = s.rtcall(ir.Syms.TypeAssert, true, []*types.Type{byteptr}, d, typ)[0]
6807		} else {
6808			var fn *obj.LSym
6809			if commaok {
6810				fn = ir.Syms.AssertE2I2
6811			} else {
6812				fn = ir.Syms.AssertE2I
6813			}
6814			itab = s.rtcall(fn, true, []*types.Type{byteptr}, target, typ)[0]
6815		}
6816		s.vars[typVar] = itab
6817		b = s.endBlock()
6818		b.AddEdgeTo(bMerge)
6819
6820		// Build resulting interface.
6821		s.startBlock(bMerge)
6822		itab = s.variable(typVar, byteptr)
6823		var ok *ssa.Value
6824		if commaok {
6825			ok = s.newValue2(ssa.OpNeqPtr, types.Types[types.TBOOL], itab, s.constNil(byteptr))
6826		}
6827		return s.newValue2(ssa.OpIMake, dst, itab, data), ok
6828	}
6829
6830	if base.Debug.TypeAssert > 0 {
6831		base.WarnfAt(pos, "type assertion inlined")
6832	}
6833
6834	// Converting to a concrete type.
6835	direct := types.IsDirectIface(dst)
6836	itab := s.newValue1(ssa.OpITab, byteptr, iface) // type word of interface
6837	if base.Debug.TypeAssert > 0 {
6838		base.WarnfAt(pos, "type assertion inlined")
6839	}
6840	var wantedFirstWord *ssa.Value
6841	if src.IsEmptyInterface() {
6842		// Looking for pointer to target type.
6843		wantedFirstWord = target
6844	} else {
6845		// Looking for pointer to itab for target type and source interface.
6846		wantedFirstWord = targetItab
6847	}
6848
6849	var tmp ir.Node     // temporary for use with large types
6850	var addr *ssa.Value // address of tmp
6851	if commaok && !ssa.CanSSA(dst) {
6852		// unSSAable type, use temporary.
6853		// TODO: get rid of some of these temporaries.
6854		tmp, addr = s.temp(pos, dst)
6855	}
6856
6857	cond := s.newValue2(ssa.OpEqPtr, types.Types[types.TBOOL], itab, wantedFirstWord)
6858	b := s.endBlock()
6859	b.Kind = ssa.BlockIf
6860	b.SetControl(cond)
6861	b.Likely = ssa.BranchLikely
6862
6863	bOk := s.f.NewBlock(ssa.BlockPlain)
6864	bFail := s.f.NewBlock(ssa.BlockPlain)
6865	b.AddEdgeTo(bOk)
6866	b.AddEdgeTo(bFail)
6867
6868	if !commaok {
6869		// on failure, panic by calling panicdottype
6870		s.startBlock(bFail)
6871		taddr := source
6872		if taddr == nil {
6873			taddr = s.reflectType(src)
6874		}
6875		if src.IsEmptyInterface() {
6876			s.rtcall(ir.Syms.PanicdottypeE, false, nil, itab, target, taddr)
6877		} else {
6878			s.rtcall(ir.Syms.PanicdottypeI, false, nil, itab, target, taddr)
6879		}
6880
6881		// on success, return data from interface
6882		s.startBlock(bOk)
6883		if direct {
6884			return s.newValue1(ssa.OpIData, dst, iface), nil
6885		}
6886		p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface)
6887		return s.load(dst, p), nil
6888	}
6889
6890	// commaok is the more complicated case because we have
6891	// a control flow merge point.
6892	bEnd := s.f.NewBlock(ssa.BlockPlain)
6893	// Note that we need a new valVar each time (unlike okVar where we can
6894	// reuse the variable) because it might have a different type every time.
6895	valVar := ssaMarker("val")
6896
6897	// type assertion succeeded
6898	s.startBlock(bOk)
6899	if tmp == nil {
6900		if direct {
6901			s.vars[valVar] = s.newValue1(ssa.OpIData, dst, iface)
6902		} else {
6903			p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface)
6904			s.vars[valVar] = s.load(dst, p)
6905		}
6906	} else {
6907		p := s.newValue1(ssa.OpIData, types.NewPtr(dst), iface)
6908		s.move(dst, addr, p)
6909	}
6910	s.vars[okVar] = s.constBool(true)
6911	s.endBlock()
6912	bOk.AddEdgeTo(bEnd)
6913
6914	// type assertion failed
6915	s.startBlock(bFail)
6916	if tmp == nil {
6917		s.vars[valVar] = s.zeroVal(dst)
6918	} else {
6919		s.zero(dst, addr)
6920	}
6921	s.vars[okVar] = s.constBool(false)
6922	s.endBlock()
6923	bFail.AddEdgeTo(bEnd)
6924
6925	// merge point
6926	s.startBlock(bEnd)
6927	if tmp == nil {
6928		res = s.variable(valVar, dst)
6929		delete(s.vars, valVar) // no practical effect, just to indicate typVar is no longer live.
6930	} else {
6931		res = s.load(dst, addr)
6932	}
6933	resok = s.variable(okVar, types.Types[types.TBOOL])
6934	delete(s.vars, okVar) // ditto
6935	return res, resok
6936}
6937
6938// temp allocates a temp of type t at position pos
6939func (s *state) temp(pos src.XPos, t *types.Type) (*ir.Name, *ssa.Value) {
6940	tmp := typecheck.TempAt(pos, s.curfn, t)
6941	if t.HasPointers() || (ssa.IsMergeCandidate(tmp) && t != deferstruct()) {
6942		s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp, s.mem())
6943	}
6944	addr := s.addr(tmp)
6945	return tmp, addr
6946}
6947
6948// variable returns the value of a variable at the current location.
6949func (s *state) variable(n ir.Node, t *types.Type) *ssa.Value {
6950	v := s.vars[n]
6951	if v != nil {
6952		return v
6953	}
6954	v = s.fwdVars[n]
6955	if v != nil {
6956		return v
6957	}
6958
6959	if s.curBlock == s.f.Entry {
6960		// No variable should be live at entry.
6961		s.f.Fatalf("value %v (%v) incorrectly live at entry", n, v)
6962	}
6963	// Make a FwdRef, which records a value that's live on block input.
6964	// We'll find the matching definition as part of insertPhis.
6965	v = s.newValue0A(ssa.OpFwdRef, t, fwdRefAux{N: n})
6966	s.fwdVars[n] = v
6967	if n.Op() == ir.ONAME {
6968		s.addNamedValue(n.(*ir.Name), v)
6969	}
6970	return v
6971}
6972
6973func (s *state) mem() *ssa.Value {
6974	return s.variable(memVar, types.TypeMem)
6975}
6976
6977func (s *state) addNamedValue(n *ir.Name, v *ssa.Value) {
6978	if n.Class == ir.Pxxx {
6979		// Don't track our marker nodes (memVar etc.).
6980		return
6981	}
6982	if ir.IsAutoTmp(n) {
6983		// Don't track temporary variables.
6984		return
6985	}
6986	if n.Class == ir.PPARAMOUT {
6987		// Don't track named output values.  This prevents return values
6988		// from being assigned too early. See #14591 and #14762. TODO: allow this.
6989		return
6990	}
6991	loc := ssa.LocalSlot{N: n, Type: n.Type(), Off: 0}
6992	values, ok := s.f.NamedValues[loc]
6993	if !ok {
6994		s.f.Names = append(s.f.Names, &loc)
6995		s.f.CanonicalLocalSlots[loc] = &loc
6996	}
6997	s.f.NamedValues[loc] = append(values, v)
6998}
6999
7000// Branch is an unresolved branch.
7001type Branch struct {
7002	P *obj.Prog  // branch instruction
7003	B *ssa.Block // target
7004}
7005
7006// State contains state needed during Prog generation.
7007type State struct {
7008	ABI obj.ABI
7009
7010	pp *objw.Progs
7011
7012	// Branches remembers all the branch instructions we've seen
7013	// and where they would like to go.
7014	Branches []Branch
7015
7016	// JumpTables remembers all the jump tables we've seen.
7017	JumpTables []*ssa.Block
7018
7019	// bstart remembers where each block starts (indexed by block ID)
7020	bstart []*obj.Prog
7021
7022	maxarg int64 // largest frame size for arguments to calls made by the function
7023
7024	// Map from GC safe points to liveness index, generated by
7025	// liveness analysis.
7026	livenessMap liveness.Map
7027
7028	// partLiveArgs includes arguments that may be partially live, for which we
7029	// need to generate instructions that spill the argument registers.
7030	partLiveArgs map[*ir.Name]bool
7031
7032	// lineRunStart records the beginning of the current run of instructions
7033	// within a single block sharing the same line number
7034	// Used to move statement marks to the beginning of such runs.
7035	lineRunStart *obj.Prog
7036
7037	// wasm: The number of values on the WebAssembly stack. This is only used as a safeguard.
7038	OnWasmStackSkipped int
7039}
7040
7041func (s *State) FuncInfo() *obj.FuncInfo {
7042	return s.pp.CurFunc.LSym.Func()
7043}
7044
7045// Prog appends a new Prog.
7046func (s *State) Prog(as obj.As) *obj.Prog {
7047	p := s.pp.Prog(as)
7048	if objw.LosesStmtMark(as) {
7049		return p
7050	}
7051	// Float a statement start to the beginning of any same-line run.
7052	// lineRunStart is reset at block boundaries, which appears to work well.
7053	if s.lineRunStart == nil || s.lineRunStart.Pos.Line() != p.Pos.Line() {
7054		s.lineRunStart = p
7055	} else if p.Pos.IsStmt() == src.PosIsStmt {
7056		s.lineRunStart.Pos = s.lineRunStart.Pos.WithIsStmt()
7057		p.Pos = p.Pos.WithNotStmt()
7058	}
7059	return p
7060}
7061
7062// Pc returns the current Prog.
7063func (s *State) Pc() *obj.Prog {
7064	return s.pp.Next
7065}
7066
7067// SetPos sets the current source position.
7068func (s *State) SetPos(pos src.XPos) {
7069	s.pp.Pos = pos
7070}
7071
7072// Br emits a single branch instruction and returns the instruction.
7073// Not all architectures need the returned instruction, but otherwise
7074// the boilerplate is common to all.
7075func (s *State) Br(op obj.As, target *ssa.Block) *obj.Prog {
7076	p := s.Prog(op)
7077	p.To.Type = obj.TYPE_BRANCH
7078	s.Branches = append(s.Branches, Branch{P: p, B: target})
7079	return p
7080}
7081
7082// DebugFriendlySetPosFrom adjusts Pos.IsStmt subject to heuristics
7083// that reduce "jumpy" line number churn when debugging.
7084// Spill/fill/copy instructions from the register allocator,
7085// phi functions, and instructions with a no-pos position
7086// are examples of instructions that can cause churn.
7087func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
7088	switch v.Op {
7089	case ssa.OpPhi, ssa.OpCopy, ssa.OpLoadReg, ssa.OpStoreReg:
7090		// These are not statements
7091		s.SetPos(v.Pos.WithNotStmt())
7092	default:
7093		p := v.Pos
7094		if p != src.NoXPos {
7095			// If the position is defined, update the position.
7096			// Also convert default IsStmt to NotStmt; only
7097			// explicit statement boundaries should appear
7098			// in the generated code.
7099			if p.IsStmt() != src.PosIsStmt {
7100				if s.pp.Pos.IsStmt() == src.PosIsStmt && s.pp.Pos.SameFileAndLine(p) {
7101					// If s.pp.Pos already has a statement mark, then it was set here (below) for
7102					// the previous value.  If an actual instruction had been emitted for that
7103					// value, then the statement mark would have been reset.  Since the statement
7104					// mark of s.pp.Pos was not reset, this position (file/line) still needs a
7105					// statement mark on an instruction.  If file and line for this value are
7106					// the same as the previous value, then the first instruction for this
7107					// value will work to take the statement mark.  Return early to avoid
7108					// resetting the statement mark.
7109					//
7110					// The reset of s.pp.Pos occurs in (*Progs).Prog() -- if it emits
7111					// an instruction, and the instruction's statement mark was set,
7112					// and it is not one of the LosesStmtMark instructions,
7113					// then Prog() resets the statement mark on the (*Progs).Pos.
7114					return
7115				}
7116				p = p.WithNotStmt()
7117				// Calls use the pos attached to v, but copy the statement mark from State
7118			}
7119			s.SetPos(p)
7120		} else {
7121			s.SetPos(s.pp.Pos.WithNotStmt())
7122		}
7123	}
7124}
7125
7126// emit argument info (locations on stack) for traceback.
7127func emitArgInfo(e *ssafn, f *ssa.Func, pp *objw.Progs) {
7128	ft := e.curfn.Type()
7129	if ft.NumRecvs() == 0 && ft.NumParams() == 0 {
7130		return
7131	}
7132
7133	x := EmitArgInfo(e.curfn, f.OwnAux.ABIInfo())
7134	x.Set(obj.AttrContentAddressable, true)
7135	e.curfn.LSym.Func().ArgInfo = x
7136
7137	// Emit a funcdata pointing at the arg info data.
7138	p := pp.Prog(obj.AFUNCDATA)
7139	p.From.SetConst(rtabi.FUNCDATA_ArgInfo)
7140	p.To.Type = obj.TYPE_MEM
7141	p.To.Name = obj.NAME_EXTERN
7142	p.To.Sym = x
7143}
7144
7145// emit argument info (locations on stack) of f for traceback.
7146func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
7147	x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI))
7148	// NOTE: do not set ContentAddressable here. This may be referenced from
7149	// assembly code by name (in this case f is a declaration).
7150	// Instead, set it in emitArgInfo above.
7151
7152	PtrSize := int64(types.PtrSize)
7153	uintptrTyp := types.Types[types.TUINTPTR]
7154
7155	isAggregate := func(t *types.Type) bool {
7156		return t.IsStruct() || t.IsArray() || t.IsComplex() || t.IsInterface() || t.IsString() || t.IsSlice()
7157	}
7158
7159	wOff := 0
7160	n := 0
7161	writebyte := func(o uint8) { wOff = objw.Uint8(x, wOff, o) }
7162
7163	// Write one non-aggregate arg/field/element.
7164	write1 := func(sz, offset int64) {
7165		if offset >= rtabi.TraceArgsSpecial {
7166			writebyte(rtabi.TraceArgsOffsetTooLarge)
7167		} else {
7168			writebyte(uint8(offset))
7169			writebyte(uint8(sz))
7170		}
7171		n++
7172	}
7173
7174	// Visit t recursively and write it out.
7175	// Returns whether to continue visiting.
7176	var visitType func(baseOffset int64, t *types.Type, depth int) bool
7177	visitType = func(baseOffset int64, t *types.Type, depth int) bool {
7178		if n >= rtabi.TraceArgsLimit {
7179			writebyte(rtabi.TraceArgsDotdotdot)
7180			return false
7181		}
7182		if !isAggregate(t) {
7183			write1(t.Size(), baseOffset)
7184			return true
7185		}
7186		writebyte(rtabi.TraceArgsStartAgg)
7187		depth++
7188		if depth >= rtabi.TraceArgsMaxDepth {
7189			writebyte(rtabi.TraceArgsDotdotdot)
7190			writebyte(rtabi.TraceArgsEndAgg)
7191			n++
7192			return true
7193		}
7194		switch {
7195		case t.IsInterface(), t.IsString():
7196			_ = visitType(baseOffset, uintptrTyp, depth) &&
7197				visitType(baseOffset+PtrSize, uintptrTyp, depth)
7198		case t.IsSlice():
7199			_ = visitType(baseOffset, uintptrTyp, depth) &&
7200				visitType(baseOffset+PtrSize, uintptrTyp, depth) &&
7201				visitType(baseOffset+PtrSize*2, uintptrTyp, depth)
7202		case t.IsComplex():
7203			_ = visitType(baseOffset, types.FloatForComplex(t), depth) &&
7204				visitType(baseOffset+t.Size()/2, types.FloatForComplex(t), depth)
7205		case t.IsArray():
7206			if t.NumElem() == 0 {
7207				n++ // {} counts as a component
7208				break
7209			}
7210			for i := int64(0); i < t.NumElem(); i++ {
7211				if !visitType(baseOffset, t.Elem(), depth) {
7212					break
7213				}
7214				baseOffset += t.Elem().Size()
7215			}
7216		case t.IsStruct():
7217			if t.NumFields() == 0 {
7218				n++ // {} counts as a component
7219				break
7220			}
7221			for _, field := range t.Fields() {
7222				if !visitType(baseOffset+field.Offset, field.Type, depth) {
7223					break
7224				}
7225			}
7226		}
7227		writebyte(rtabi.TraceArgsEndAgg)
7228		return true
7229	}
7230
7231	start := 0
7232	if strings.Contains(f.LSym.Name, "[") {
7233		// Skip the dictionary argument - it is implicit and the user doesn't need to see it.
7234		start = 1
7235	}
7236
7237	for _, a := range abiInfo.InParams()[start:] {
7238		if !visitType(a.FrameOffset(abiInfo), a.Type, 0) {
7239			break
7240		}
7241	}
7242	writebyte(rtabi.TraceArgsEndSeq)
7243	if wOff > rtabi.TraceArgsMaxLen {
7244		base.Fatalf("ArgInfo too large")
7245	}
7246
7247	return x
7248}
7249
7250// for wrapper, emit info of wrapped function.
7251func emitWrappedFuncInfo(e *ssafn, pp *objw.Progs) {
7252	if base.Ctxt.Flag_linkshared {
7253		// Relative reference (SymPtrOff) to another shared object doesn't work.
7254		// Unfortunate.
7255		return
7256	}
7257
7258	wfn := e.curfn.WrappedFunc
7259	if wfn == nil {
7260		return
7261	}
7262
7263	wsym := wfn.Linksym()
7264	x := base.Ctxt.LookupInit(fmt.Sprintf("%s.wrapinfo", wsym.Name), func(x *obj.LSym) {
7265		objw.SymPtrOff(x, 0, wsym)
7266		x.Set(obj.AttrContentAddressable, true)
7267	})
7268	e.curfn.LSym.Func().WrapInfo = x
7269
7270	// Emit a funcdata pointing at the wrap info data.
7271	p := pp.Prog(obj.AFUNCDATA)
7272	p.From.SetConst(rtabi.FUNCDATA_WrapInfo)
7273	p.To.Type = obj.TYPE_MEM
7274	p.To.Name = obj.NAME_EXTERN
7275	p.To.Sym = x
7276}
7277
7278// genssa appends entries to pp for each instruction in f.
7279func genssa(f *ssa.Func, pp *objw.Progs) {
7280	var s State
7281	s.ABI = f.OwnAux.Fn.ABI()
7282
7283	e := f.Frontend().(*ssafn)
7284
7285	s.livenessMap, s.partLiveArgs = liveness.Compute(e.curfn, f, e.stkptrsize, pp)
7286	emitArgInfo(e, f, pp)
7287	argLiveBlockMap, argLiveValueMap := liveness.ArgLiveness(e.curfn, f, pp)
7288
7289	openDeferInfo := e.curfn.LSym.Func().OpenCodedDeferInfo
7290	if openDeferInfo != nil {
7291		// This function uses open-coded defers -- write out the funcdata
7292		// info that we computed at the end of genssa.
7293		p := pp.Prog(obj.AFUNCDATA)
7294		p.From.SetConst(rtabi.FUNCDATA_OpenCodedDeferInfo)
7295		p.To.Type = obj.TYPE_MEM
7296		p.To.Name = obj.NAME_EXTERN
7297		p.To.Sym = openDeferInfo
7298	}
7299
7300	emitWrappedFuncInfo(e, pp)
7301
7302	// Remember where each block starts.
7303	s.bstart = make([]*obj.Prog, f.NumBlocks())
7304	s.pp = pp
7305	var progToValue map[*obj.Prog]*ssa.Value
7306	var progToBlock map[*obj.Prog]*ssa.Block
7307	var valueToProgAfter []*obj.Prog // The first Prog following computation of a value v; v is visible at this point.
7308	gatherPrintInfo := f.PrintOrHtmlSSA || ssa.GenssaDump[f.Name]
7309	if gatherPrintInfo {
7310		progToValue = make(map[*obj.Prog]*ssa.Value, f.NumValues())
7311		progToBlock = make(map[*obj.Prog]*ssa.Block, f.NumBlocks())
7312		f.Logf("genssa %s\n", f.Name)
7313		progToBlock[s.pp.Next] = f.Blocks[0]
7314	}
7315
7316	if base.Ctxt.Flag_locationlists {
7317		if cap(f.Cache.ValueToProgAfter) < f.NumValues() {
7318			f.Cache.ValueToProgAfter = make([]*obj.Prog, f.NumValues())
7319		}
7320		valueToProgAfter = f.Cache.ValueToProgAfter[:f.NumValues()]
7321		for i := range valueToProgAfter {
7322			valueToProgAfter[i] = nil
7323		}
7324	}
7325
7326	// If the very first instruction is not tagged as a statement,
7327	// debuggers may attribute it to previous function in program.
7328	firstPos := src.NoXPos
7329	for _, v := range f.Entry.Values {
7330		if v.Pos.IsStmt() == src.PosIsStmt && v.Op != ssa.OpArg && v.Op != ssa.OpArgIntReg && v.Op != ssa.OpArgFloatReg && v.Op != ssa.OpLoadReg && v.Op != ssa.OpStoreReg {
7331			firstPos = v.Pos
7332			v.Pos = firstPos.WithDefaultStmt()
7333			break
7334		}
7335	}
7336
7337	// inlMarks has an entry for each Prog that implements an inline mark.
7338	// It maps from that Prog to the global inlining id of the inlined body
7339	// which should unwind to this Prog's location.
7340	var inlMarks map[*obj.Prog]int32
7341	var inlMarkList []*obj.Prog
7342
7343	// inlMarksByPos maps from a (column 1) source position to the set of
7344	// Progs that are in the set above and have that source position.
7345	var inlMarksByPos map[src.XPos][]*obj.Prog
7346
7347	var argLiveIdx int = -1 // argument liveness info index
7348
7349	// These control cache line alignment; if the required portion of
7350	// a cache line is not available, then pad to obtain cache line
7351	// alignment.  Not implemented on all architectures, may not be
7352	// useful on all architectures.
7353	var hotAlign, hotRequire int64
7354
7355	if base.Debug.AlignHot > 0 {
7356		switch base.Ctxt.Arch.Name {
7357		// enable this on a case-by-case basis, with benchmarking.
7358		// currently shown:
7359		//   good for amd64
7360		//   not helpful for Apple Silicon
7361		//
7362		case "amd64", "386":
7363			// Align to 64 if 31 or fewer bytes remain in a cache line
7364			// benchmarks a little better than always aligning, and also
7365			// adds slightly less to the (PGO-compiled) binary size.
7366			hotAlign = 64
7367			hotRequire = 31
7368		}
7369	}
7370
7371	// Emit basic blocks
7372	for i, b := range f.Blocks {
7373
7374		s.lineRunStart = nil
7375		s.SetPos(s.pp.Pos.WithNotStmt()) // It needs a non-empty Pos, but cannot be a statement boundary (yet).
7376
7377		if hotAlign > 0 && b.Hotness&ssa.HotPgoInitial == ssa.HotPgoInitial {
7378			// So far this has only been shown profitable for PGO-hot loop headers.
7379			// The Hotness values allows distinctions betwen initial blocks that are "hot" or not, and "flow-in" or not.
7380			// Currently only the initial blocks of loops are tagged in this way;
7381			// there are no blocks tagged "pgo-hot" that are not also tagged "initial".
7382			// TODO more heuristics, more architectures.
7383			p := s.pp.Prog(obj.APCALIGNMAX)
7384			p.From.SetConst(hotAlign)
7385			p.To.SetConst(hotRequire)
7386		}
7387
7388		s.bstart[b.ID] = s.pp.Next
7389
7390		if idx, ok := argLiveBlockMap[b.ID]; ok && idx != argLiveIdx {
7391			argLiveIdx = idx
7392			p := s.pp.Prog(obj.APCDATA)
7393			p.From.SetConst(rtabi.PCDATA_ArgLiveIndex)
7394			p.To.SetConst(int64(idx))
7395		}
7396
7397		// Emit values in block
7398		Arch.SSAMarkMoves(&s, b)
7399		for _, v := range b.Values {
7400			x := s.pp.Next
7401			s.DebugFriendlySetPosFrom(v)
7402
7403			if v.Op.ResultInArg0() && v.ResultReg() != v.Args[0].Reg() {
7404				v.Fatalf("input[0] and output not in same register %s", v.LongString())
7405			}
7406
7407			switch v.Op {
7408			case ssa.OpInitMem:
7409				// memory arg needs no code
7410			case ssa.OpArg:
7411				// input args need no code
7412			case ssa.OpSP, ssa.OpSB:
7413				// nothing to do
7414			case ssa.OpSelect0, ssa.OpSelect1, ssa.OpSelectN, ssa.OpMakeResult:
7415				// nothing to do
7416			case ssa.OpGetG:
7417				// nothing to do when there's a g register,
7418				// and checkLower complains if there's not
7419			case ssa.OpVarDef, ssa.OpVarLive, ssa.OpKeepAlive, ssa.OpWBend:
7420				// nothing to do; already used by liveness
7421			case ssa.OpPhi:
7422				CheckLoweredPhi(v)
7423			case ssa.OpConvert:
7424				// nothing to do; no-op conversion for liveness
7425				if v.Args[0].Reg() != v.Reg() {
7426					v.Fatalf("OpConvert should be a no-op: %s; %s", v.Args[0].LongString(), v.LongString())
7427				}
7428			case ssa.OpInlMark:
7429				p := Arch.Ginsnop(s.pp)
7430				if inlMarks == nil {
7431					inlMarks = map[*obj.Prog]int32{}
7432					inlMarksByPos = map[src.XPos][]*obj.Prog{}
7433				}
7434				inlMarks[p] = v.AuxInt32()
7435				inlMarkList = append(inlMarkList, p)
7436				pos := v.Pos.AtColumn1()
7437				inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
7438				firstPos = src.NoXPos
7439
7440			default:
7441				// Special case for first line in function; move it to the start (which cannot be a register-valued instruction)
7442				if firstPos != src.NoXPos && v.Op != ssa.OpArgIntReg && v.Op != ssa.OpArgFloatReg && v.Op != ssa.OpLoadReg && v.Op != ssa.OpStoreReg {
7443					s.SetPos(firstPos)
7444					firstPos = src.NoXPos
7445				}
7446				// Attach this safe point to the next
7447				// instruction.
7448				s.pp.NextLive = s.livenessMap.Get(v)
7449				s.pp.NextUnsafe = s.livenessMap.GetUnsafe(v)
7450
7451				// let the backend handle it
7452				Arch.SSAGenValue(&s, v)
7453			}
7454
7455			if idx, ok := argLiveValueMap[v.ID]; ok && idx != argLiveIdx {
7456				argLiveIdx = idx
7457				p := s.pp.Prog(obj.APCDATA)
7458				p.From.SetConst(rtabi.PCDATA_ArgLiveIndex)
7459				p.To.SetConst(int64(idx))
7460			}
7461
7462			if base.Ctxt.Flag_locationlists {
7463				valueToProgAfter[v.ID] = s.pp.Next
7464			}
7465
7466			if gatherPrintInfo {
7467				for ; x != s.pp.Next; x = x.Link {
7468					progToValue[x] = v
7469				}
7470			}
7471		}
7472		// If this is an empty infinite loop, stick a hardware NOP in there so that debuggers are less confused.
7473		if s.bstart[b.ID] == s.pp.Next && len(b.Succs) == 1 && b.Succs[0].Block() == b {
7474			p := Arch.Ginsnop(s.pp)
7475			p.Pos = p.Pos.WithIsStmt()
7476			if b.Pos == src.NoXPos {
7477				b.Pos = p.Pos // It needs a file, otherwise a no-file non-zero line causes confusion.  See #35652.
7478				if b.Pos == src.NoXPos {
7479					b.Pos = s.pp.Text.Pos // Sometimes p.Pos is empty.  See #35695.
7480				}
7481			}
7482			b.Pos = b.Pos.WithBogusLine() // Debuggers are not good about infinite loops, force a change in line number
7483		}
7484
7485		// Set unsafe mark for any end-of-block generated instructions
7486		// (normally, conditional or unconditional branches).
7487		// This is particularly important for empty blocks, as there
7488		// are no values to inherit the unsafe mark from.
7489		s.pp.NextUnsafe = s.livenessMap.GetUnsafeBlock(b)
7490
7491		// Emit control flow instructions for block
7492		var next *ssa.Block
7493		if i < len(f.Blocks)-1 && base.Flag.N == 0 {
7494			// If -N, leave next==nil so every block with successors
7495			// ends in a JMP (except call blocks - plive doesn't like
7496			// select{send,recv} followed by a JMP call).  Helps keep
7497			// line numbers for otherwise empty blocks.
7498			next = f.Blocks[i+1]
7499		}
7500		x := s.pp.Next
7501		s.SetPos(b.Pos)
7502		Arch.SSAGenBlock(&s, b, next)
7503		if gatherPrintInfo {
7504			for ; x != s.pp.Next; x = x.Link {
7505				progToBlock[x] = b
7506			}
7507		}
7508	}
7509	if f.Blocks[len(f.Blocks)-1].Kind == ssa.BlockExit {
7510		// We need the return address of a panic call to
7511		// still be inside the function in question. So if
7512		// it ends in a call which doesn't return, add a
7513		// nop (which will never execute) after the call.
7514		Arch.Ginsnop(s.pp)
7515	}
7516	if openDeferInfo != nil {
7517		// When doing open-coded defers, generate a disconnected call to
7518		// deferreturn and a return. This will be used to during panic
7519		// recovery to unwind the stack and return back to the runtime.
7520		s.pp.NextLive = s.livenessMap.DeferReturn
7521		p := s.pp.Prog(obj.ACALL)
7522		p.To.Type = obj.TYPE_MEM
7523		p.To.Name = obj.NAME_EXTERN
7524		p.To.Sym = ir.Syms.Deferreturn
7525
7526		// Load results into registers. So when a deferred function
7527		// recovers a panic, it will return to caller with right results.
7528		// The results are already in memory, because they are not SSA'd
7529		// when the function has defers (see canSSAName).
7530		for _, o := range f.OwnAux.ABIInfo().OutParams() {
7531			n := o.Name
7532			rts, offs := o.RegisterTypesAndOffsets()
7533			for i := range o.Registers {
7534				Arch.LoadRegResult(&s, f, rts[i], ssa.ObjRegForAbiReg(o.Registers[i], f.Config), n, offs[i])
7535			}
7536		}
7537
7538		s.pp.Prog(obj.ARET)
7539	}
7540
7541	if inlMarks != nil {
7542		hasCall := false
7543
7544		// We have some inline marks. Try to find other instructions we're
7545		// going to emit anyway, and use those instructions instead of the
7546		// inline marks.
7547		for p := s.pp.Text; p != nil; p = p.Link {
7548			if p.As == obj.ANOP || p.As == obj.AFUNCDATA || p.As == obj.APCDATA || p.As == obj.ATEXT ||
7549				p.As == obj.APCALIGN || p.As == obj.APCALIGNMAX || Arch.LinkArch.Family == sys.Wasm {
7550				// Don't use 0-sized instructions as inline marks, because we need
7551				// to identify inline mark instructions by pc offset.
7552				// (Some of these instructions are sometimes zero-sized, sometimes not.
7553				// We must not use anything that even might be zero-sized.)
7554				// TODO: are there others?
7555				continue
7556			}
7557			if _, ok := inlMarks[p]; ok {
7558				// Don't use inline marks themselves. We don't know
7559				// whether they will be zero-sized or not yet.
7560				continue
7561			}
7562			if p.As == obj.ACALL || p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
7563				hasCall = true
7564			}
7565			pos := p.Pos.AtColumn1()
7566			marks := inlMarksByPos[pos]
7567			if len(marks) == 0 {
7568				continue
7569			}
7570			for _, m := range marks {
7571				// We found an instruction with the same source position as
7572				// some of the inline marks.
7573				// Use this instruction instead.
7574				p.Pos = p.Pos.WithIsStmt() // promote position to a statement
7575				s.pp.CurFunc.LSym.Func().AddInlMark(p, inlMarks[m])
7576				// Make the inline mark a real nop, so it doesn't generate any code.
7577				m.As = obj.ANOP
7578				m.Pos = src.NoXPos
7579				m.From = obj.Addr{}
7580				m.To = obj.Addr{}
7581			}
7582			delete(inlMarksByPos, pos)
7583		}
7584		// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
7585		for _, p := range inlMarkList {
7586			if p.As != obj.ANOP {
7587				s.pp.CurFunc.LSym.Func().AddInlMark(p, inlMarks[p])
7588			}
7589		}
7590
7591		if e.stksize == 0 && !hasCall {
7592			// Frameless leaf function. It doesn't need any preamble,
7593			// so make sure its first instruction isn't from an inlined callee.
7594			// If it is, add a nop at the start of the function with a position
7595			// equal to the start of the function.
7596			// This ensures that runtime.FuncForPC(uintptr(reflect.ValueOf(fn).Pointer())).Name()
7597			// returns the right answer. See issue 58300.
7598			for p := s.pp.Text; p != nil; p = p.Link {
7599				if p.As == obj.AFUNCDATA || p.As == obj.APCDATA || p.As == obj.ATEXT || p.As == obj.ANOP {
7600					continue
7601				}
7602				if base.Ctxt.PosTable.Pos(p.Pos).Base().InliningIndex() >= 0 {
7603					// Make a real (not 0-sized) nop.
7604					nop := Arch.Ginsnop(s.pp)
7605					nop.Pos = e.curfn.Pos().WithIsStmt()
7606
7607					// Unfortunately, Ginsnop puts the instruction at the
7608					// end of the list. Move it up to just before p.
7609
7610					// Unlink from the current list.
7611					for x := s.pp.Text; x != nil; x = x.Link {
7612						if x.Link == nop {
7613							x.Link = nop.Link
7614							break
7615						}
7616					}
7617					// Splice in right before p.
7618					for x := s.pp.Text; x != nil; x = x.Link {
7619						if x.Link == p {
7620							nop.Link = p
7621							x.Link = nop
7622							break
7623						}
7624					}
7625				}
7626				break
7627			}
7628		}
7629	}
7630
7631	if base.Ctxt.Flag_locationlists {
7632		var debugInfo *ssa.FuncDebug
7633		debugInfo = e.curfn.DebugInfo.(*ssa.FuncDebug)
7634		if e.curfn.ABI == obj.ABIInternal && base.Flag.N != 0 {
7635			ssa.BuildFuncDebugNoOptimized(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset, debugInfo)
7636		} else {
7637			ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists, StackOffset, debugInfo)
7638		}
7639		bstart := s.bstart
7640		idToIdx := make([]int, f.NumBlocks())
7641		for i, b := range f.Blocks {
7642			idToIdx[b.ID] = i
7643		}
7644		// Register a callback that will be used later to fill in PCs into location
7645		// lists. At the moment, Prog.Pc is a sequence number; it's not a real PC
7646		// until after assembly, so the translation needs to be deferred.
7647		debugInfo.GetPC = func(b, v ssa.ID) int64 {
7648			switch v {
7649			case ssa.BlockStart.ID:
7650				if b == f.Entry.ID {
7651					return 0 // Start at the very beginning, at the assembler-generated prologue.
7652					// this should only happen for function args (ssa.OpArg)
7653				}
7654				return bstart[b].Pc
7655			case ssa.BlockEnd.ID:
7656				blk := f.Blocks[idToIdx[b]]
7657				nv := len(blk.Values)
7658				return valueToProgAfter[blk.Values[nv-1].ID].Pc
7659			case ssa.FuncEnd.ID:
7660				return e.curfn.LSym.Size
7661			default:
7662				return valueToProgAfter[v].Pc
7663			}
7664		}
7665	}
7666
7667	// Resolve branches, and relax DefaultStmt into NotStmt
7668	for _, br := range s.Branches {
7669		br.P.To.SetTarget(s.bstart[br.B.ID])
7670		if br.P.Pos.IsStmt() != src.PosIsStmt {
7671			br.P.Pos = br.P.Pos.WithNotStmt()
7672		} else if v0 := br.B.FirstPossibleStmtValue(); v0 != nil && v0.Pos.Line() == br.P.Pos.Line() && v0.Pos.IsStmt() == src.PosIsStmt {
7673			br.P.Pos = br.P.Pos.WithNotStmt()
7674		}
7675
7676	}
7677
7678	// Resolve jump table destinations.
7679	for _, jt := range s.JumpTables {
7680		// Convert from *Block targets to *Prog targets.
7681		targets := make([]*obj.Prog, len(jt.Succs))
7682		for i, e := range jt.Succs {
7683			targets[i] = s.bstart[e.Block().ID]
7684		}
7685		// Add to list of jump tables to be resolved at assembly time.
7686		// The assembler converts from *Prog entries to absolute addresses
7687		// once it knows instruction byte offsets.
7688		fi := s.pp.CurFunc.LSym.Func()
7689		fi.JumpTables = append(fi.JumpTables, obj.JumpTable{Sym: jt.Aux.(*obj.LSym), Targets: targets})
7690	}
7691
7692	if e.log { // spew to stdout
7693		filename := ""
7694		for p := s.pp.Text; p != nil; p = p.Link {
7695			if p.Pos.IsKnown() && p.InnermostFilename() != filename {
7696				filename = p.InnermostFilename()
7697				f.Logf("# %s\n", filename)
7698			}
7699
7700			var s string
7701			if v, ok := progToValue[p]; ok {
7702				s = v.String()
7703			} else if b, ok := progToBlock[p]; ok {
7704				s = b.String()
7705			} else {
7706				s = "   " // most value and branch strings are 2-3 characters long
7707			}
7708			f.Logf(" %-6s\t%.5d (%s)\t%s\n", s, p.Pc, p.InnermostLineNumber(), p.InstructionString())
7709		}
7710	}
7711	if f.HTMLWriter != nil { // spew to ssa.html
7712		var buf strings.Builder
7713		buf.WriteString("<code>")
7714		buf.WriteString("<dl class=\"ssa-gen\">")
7715		filename := ""
7716		for p := s.pp.Text; p != nil; p = p.Link {
7717			// Don't spam every line with the file name, which is often huge.
7718			// Only print changes, and "unknown" is not a change.
7719			if p.Pos.IsKnown() && p.InnermostFilename() != filename {
7720				filename = p.InnermostFilename()
7721				buf.WriteString("<dt class=\"ssa-prog-src\"></dt><dd class=\"ssa-prog\">")
7722				buf.WriteString(html.EscapeString("# " + filename))
7723				buf.WriteString("</dd>")
7724			}
7725
7726			buf.WriteString("<dt class=\"ssa-prog-src\">")
7727			if v, ok := progToValue[p]; ok {
7728				buf.WriteString(v.HTML())
7729			} else if b, ok := progToBlock[p]; ok {
7730				buf.WriteString("<b>" + b.HTML() + "</b>")
7731			}
7732			buf.WriteString("</dt>")
7733			buf.WriteString("<dd class=\"ssa-prog\">")
7734			fmt.Fprintf(&buf, "%.5d <span class=\"l%v line-number\">(%s)</span> %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString()))
7735			buf.WriteString("</dd>")
7736		}
7737		buf.WriteString("</dl>")
7738		buf.WriteString("</code>")
7739		f.HTMLWriter.WriteColumn("genssa", "genssa", "ssa-prog", buf.String())
7740	}
7741	if ssa.GenssaDump[f.Name] {
7742		fi := f.DumpFileForPhase("genssa")
7743		if fi != nil {
7744
7745			// inliningDiffers if any filename changes or if any line number except the innermost (last index) changes.
7746			inliningDiffers := func(a, b []src.Pos) bool {
7747				if len(a) != len(b) {
7748					return true
7749				}
7750				for i := range a {
7751					if a[i].Filename() != b[i].Filename() {
7752						return true
7753					}
7754					if i != len(a)-1 && a[i].Line() != b[i].Line() {
7755						return true
7756					}
7757				}
7758				return false
7759			}
7760
7761			var allPosOld []src.Pos
7762			var allPos []src.Pos
7763
7764			for p := s.pp.Text; p != nil; p = p.Link {
7765				if p.Pos.IsKnown() {
7766					allPos = allPos[:0]
7767					p.Ctxt.AllPos(p.Pos, func(pos src.Pos) { allPos = append(allPos, pos) })
7768					if inliningDiffers(allPos, allPosOld) {
7769						for _, pos := range allPos {
7770							fmt.Fprintf(fi, "# %s:%d\n", pos.Filename(), pos.Line())
7771						}
7772						allPos, allPosOld = allPosOld, allPos // swap, not copy, so that they do not share slice storage.
7773					}
7774				}
7775
7776				var s string
7777				if v, ok := progToValue[p]; ok {
7778					s = v.String()
7779				} else if b, ok := progToBlock[p]; ok {
7780					s = b.String()
7781				} else {
7782					s = "   " // most value and branch strings are 2-3 characters long
7783				}
7784				fmt.Fprintf(fi, " %-6s\t%.5d %s\t%s\n", s, p.Pc, ssa.StmtString(p.Pos), p.InstructionString())
7785			}
7786			fi.Close()
7787		}
7788	}
7789
7790	defframe(&s, e, f)
7791
7792	f.HTMLWriter.Close()
7793	f.HTMLWriter = nil
7794}
7795
7796func defframe(s *State, e *ssafn, f *ssa.Func) {
7797	pp := s.pp
7798
7799	s.maxarg = types.RoundUp(s.maxarg, e.stkalign)
7800	frame := s.maxarg + e.stksize
7801	if Arch.PadFrame != nil {
7802		frame = Arch.PadFrame(frame)
7803	}
7804
7805	// Fill in argument and frame size.
7806	pp.Text.To.Type = obj.TYPE_TEXTSIZE
7807	pp.Text.To.Val = int32(types.RoundUp(f.OwnAux.ArgWidth(), int64(types.RegSize)))
7808	pp.Text.To.Offset = frame
7809
7810	p := pp.Text
7811
7812	// Insert code to spill argument registers if the named slot may be partially
7813	// live. That is, the named slot is considered live by liveness analysis,
7814	// (because a part of it is live), but we may not spill all parts into the
7815	// slot. This can only happen with aggregate-typed arguments that are SSA-able
7816	// and not address-taken (for non-SSA-able or address-taken arguments we always
7817	// spill upfront).
7818	// Note: spilling is unnecessary in the -N/no-optimize case, since all values
7819	// will be considered non-SSAable and spilled up front.
7820	// TODO(register args) Make liveness more fine-grained to that partial spilling is okay.
7821	if f.OwnAux.ABIInfo().InRegistersUsed() != 0 && base.Flag.N == 0 {
7822		// First, see if it is already spilled before it may be live. Look for a spill
7823		// in the entry block up to the first safepoint.
7824		type nameOff struct {
7825			n   *ir.Name
7826			off int64
7827		}
7828		partLiveArgsSpilled := make(map[nameOff]bool)
7829		for _, v := range f.Entry.Values {
7830			if v.Op.IsCall() {
7831				break
7832			}
7833			if v.Op != ssa.OpStoreReg || v.Args[0].Op != ssa.OpArgIntReg {
7834				continue
7835			}
7836			n, off := ssa.AutoVar(v)
7837			if n.Class != ir.PPARAM || n.Addrtaken() || !ssa.CanSSA(n.Type()) || !s.partLiveArgs[n] {
7838				continue
7839			}
7840			partLiveArgsSpilled[nameOff{n, off}] = true
7841		}
7842
7843		// Then, insert code to spill registers if not already.
7844		for _, a := range f.OwnAux.ABIInfo().InParams() {
7845			n := a.Name
7846			if n == nil || n.Addrtaken() || !ssa.CanSSA(n.Type()) || !s.partLiveArgs[n] || len(a.Registers) <= 1 {
7847				continue
7848			}
7849			rts, offs := a.RegisterTypesAndOffsets()
7850			for i := range a.Registers {
7851				if !rts[i].HasPointers() {
7852					continue
7853				}
7854				if partLiveArgsSpilled[nameOff{n, offs[i]}] {
7855					continue // already spilled
7856				}
7857				reg := ssa.ObjRegForAbiReg(a.Registers[i], f.Config)
7858				p = Arch.SpillArgReg(pp, p, f, rts[i], reg, n, offs[i])
7859			}
7860		}
7861	}
7862
7863	// Insert code to zero ambiguously live variables so that the
7864	// garbage collector only sees initialized values when it
7865	// looks for pointers.
7866	var lo, hi int64
7867
7868	// Opaque state for backend to use. Current backends use it to
7869	// keep track of which helper registers have been zeroed.
7870	var state uint32
7871
7872	// Iterate through declarations. Autos are sorted in decreasing
7873	// frame offset order.
7874	for _, n := range e.curfn.Dcl {
7875		if !n.Needzero() {
7876			continue
7877		}
7878		if n.Class != ir.PAUTO {
7879			e.Fatalf(n.Pos(), "needzero class %d", n.Class)
7880		}
7881		if n.Type().Size()%int64(types.PtrSize) != 0 || n.FrameOffset()%int64(types.PtrSize) != 0 || n.Type().Size() == 0 {
7882			e.Fatalf(n.Pos(), "var %L has size %d offset %d", n, n.Type().Size(), n.Offset_)
7883		}
7884
7885		if lo != hi && n.FrameOffset()+n.Type().Size() >= lo-int64(2*types.RegSize) {
7886			// Merge with range we already have.
7887			lo = n.FrameOffset()
7888			continue
7889		}
7890
7891		// Zero old range
7892		p = Arch.ZeroRange(pp, p, frame+lo, hi-lo, &state)
7893
7894		// Set new range.
7895		lo = n.FrameOffset()
7896		hi = lo + n.Type().Size()
7897	}
7898
7899	// Zero final range.
7900	Arch.ZeroRange(pp, p, frame+lo, hi-lo, &state)
7901}
7902
7903// For generating consecutive jump instructions to model a specific branching
7904type IndexJump struct {
7905	Jump  obj.As
7906	Index int
7907}
7908
7909func (s *State) oneJump(b *ssa.Block, jump *IndexJump) {
7910	p := s.Br(jump.Jump, b.Succs[jump.Index].Block())
7911	p.Pos = b.Pos
7912}
7913
7914// CombJump generates combinational instructions (2 at present) for a block jump,
7915// thereby the behaviour of non-standard condition codes could be simulated
7916func (s *State) CombJump(b, next *ssa.Block, jumps *[2][2]IndexJump) {
7917	switch next {
7918	case b.Succs[0].Block():
7919		s.oneJump(b, &jumps[0][0])
7920		s.oneJump(b, &jumps[0][1])
7921	case b.Succs[1].Block():
7922		s.oneJump(b, &jumps[1][0])
7923		s.oneJump(b, &jumps[1][1])
7924	default:
7925		var q *obj.Prog
7926		if b.Likely != ssa.BranchUnlikely {
7927			s.oneJump(b, &jumps[1][0])
7928			s.oneJump(b, &jumps[1][1])
7929			q = s.Br(obj.AJMP, b.Succs[1].Block())
7930		} else {
7931			s.oneJump(b, &jumps[0][0])
7932			s.oneJump(b, &jumps[0][1])
7933			q = s.Br(obj.AJMP, b.Succs[0].Block())
7934		}
7935		q.Pos = b.Pos
7936	}
7937}
7938
7939// AddAux adds the offset in the aux fields (AuxInt and Aux) of v to a.
7940func AddAux(a *obj.Addr, v *ssa.Value) {
7941	AddAux2(a, v, v.AuxInt)
7942}
7943func AddAux2(a *obj.Addr, v *ssa.Value, offset int64) {
7944	if a.Type != obj.TYPE_MEM && a.Type != obj.TYPE_ADDR {
7945		v.Fatalf("bad AddAux addr %v", a)
7946	}
7947	// add integer offset
7948	a.Offset += offset
7949
7950	// If no additional symbol offset, we're done.
7951	if v.Aux == nil {
7952		return
7953	}
7954	// Add symbol's offset from its base register.
7955	switch n := v.Aux.(type) {
7956	case *ssa.AuxCall:
7957		a.Name = obj.NAME_EXTERN
7958		a.Sym = n.Fn
7959	case *obj.LSym:
7960		a.Name = obj.NAME_EXTERN
7961		a.Sym = n
7962	case *ir.Name:
7963		if n.Class == ir.PPARAM || (n.Class == ir.PPARAMOUT && !n.IsOutputParamInRegisters()) {
7964			a.Name = obj.NAME_PARAM
7965		} else {
7966			a.Name = obj.NAME_AUTO
7967		}
7968		a.Sym = n.Linksym()
7969		a.Offset += n.FrameOffset()
7970	default:
7971		v.Fatalf("aux in %s not implemented %#v", v, v.Aux)
7972	}
7973}
7974
7975// extendIndex extends v to a full int width.
7976// panic with the given kind if v does not fit in an int (only on 32-bit archs).
7977func (s *state) extendIndex(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
7978	size := idx.Type.Size()
7979	if size == s.config.PtrSize {
7980		return idx
7981	}
7982	if size > s.config.PtrSize {
7983		// truncate 64-bit indexes on 32-bit pointer archs. Test the
7984		// high word and branch to out-of-bounds failure if it is not 0.
7985		var lo *ssa.Value
7986		if idx.Type.IsSigned() {
7987			lo = s.newValue1(ssa.OpInt64Lo, types.Types[types.TINT], idx)
7988		} else {
7989			lo = s.newValue1(ssa.OpInt64Lo, types.Types[types.TUINT], idx)
7990		}
7991		if bounded || base.Flag.B != 0 {
7992			return lo
7993		}
7994		bNext := s.f.NewBlock(ssa.BlockPlain)
7995		bPanic := s.f.NewBlock(ssa.BlockExit)
7996		hi := s.newValue1(ssa.OpInt64Hi, types.Types[types.TUINT32], idx)
7997		cmp := s.newValue2(ssa.OpEq32, types.Types[types.TBOOL], hi, s.constInt32(types.Types[types.TUINT32], 0))
7998		if !idx.Type.IsSigned() {
7999			switch kind {
8000			case ssa.BoundsIndex:
8001				kind = ssa.BoundsIndexU
8002			case ssa.BoundsSliceAlen:
8003				kind = ssa.BoundsSliceAlenU
8004			case ssa.BoundsSliceAcap:
8005				kind = ssa.BoundsSliceAcapU
8006			case ssa.BoundsSliceB:
8007				kind = ssa.BoundsSliceBU
8008			case ssa.BoundsSlice3Alen:
8009				kind = ssa.BoundsSlice3AlenU
8010			case ssa.BoundsSlice3Acap:
8011				kind = ssa.BoundsSlice3AcapU
8012			case ssa.BoundsSlice3B:
8013				kind = ssa.BoundsSlice3BU
8014			case ssa.BoundsSlice3C:
8015				kind = ssa.BoundsSlice3CU
8016			}
8017		}
8018		b := s.endBlock()
8019		b.Kind = ssa.BlockIf
8020		b.SetControl(cmp)
8021		b.Likely = ssa.BranchLikely
8022		b.AddEdgeTo(bNext)
8023		b.AddEdgeTo(bPanic)
8024
8025		s.startBlock(bPanic)
8026		mem := s.newValue4I(ssa.OpPanicExtend, types.TypeMem, int64(kind), hi, lo, len, s.mem())
8027		s.endBlock().SetControl(mem)
8028		s.startBlock(bNext)
8029
8030		return lo
8031	}
8032
8033	// Extend value to the required size
8034	var op ssa.Op
8035	if idx.Type.IsSigned() {
8036		switch 10*size + s.config.PtrSize {
8037		case 14:
8038			op = ssa.OpSignExt8to32
8039		case 18:
8040			op = ssa.OpSignExt8to64
8041		case 24:
8042			op = ssa.OpSignExt16to32
8043		case 28:
8044			op = ssa.OpSignExt16to64
8045		case 48:
8046			op = ssa.OpSignExt32to64
8047		default:
8048			s.Fatalf("bad signed index extension %s", idx.Type)
8049		}
8050	} else {
8051		switch 10*size + s.config.PtrSize {
8052		case 14:
8053			op = ssa.OpZeroExt8to32
8054		case 18:
8055			op = ssa.OpZeroExt8to64
8056		case 24:
8057			op = ssa.OpZeroExt16to32
8058		case 28:
8059			op = ssa.OpZeroExt16to64
8060		case 48:
8061			op = ssa.OpZeroExt32to64
8062		default:
8063			s.Fatalf("bad unsigned index extension %s", idx.Type)
8064		}
8065	}
8066	return s.newValue1(op, types.Types[types.TINT], idx)
8067}
8068
8069// CheckLoweredPhi checks that regalloc and stackalloc correctly handled phi values.
8070// Called during ssaGenValue.
8071func CheckLoweredPhi(v *ssa.Value) {
8072	if v.Op != ssa.OpPhi {
8073		v.Fatalf("CheckLoweredPhi called with non-phi value: %v", v.LongString())
8074	}
8075	if v.Type.IsMemory() {
8076		return
8077	}
8078	f := v.Block.Func
8079	loc := f.RegAlloc[v.ID]
8080	for _, a := range v.Args {
8081		if aloc := f.RegAlloc[a.ID]; aloc != loc { // TODO: .Equal() instead?
8082			v.Fatalf("phi arg at different location than phi: %v @ %s, but arg %v @ %s\n%s\n", v, loc, a, aloc, v.Block.Func)
8083		}
8084	}
8085}
8086
8087// CheckLoweredGetClosurePtr checks that v is the first instruction in the function's entry block,
8088// except for incoming in-register arguments.
8089// The output of LoweredGetClosurePtr is generally hardwired to the correct register.
8090// That register contains the closure pointer on closure entry.
8091func CheckLoweredGetClosurePtr(v *ssa.Value) {
8092	entry := v.Block.Func.Entry
8093	if entry != v.Block {
8094		base.Fatalf("in %s, badly placed LoweredGetClosurePtr: %v %v", v.Block.Func.Name, v.Block, v)
8095	}
8096	for _, w := range entry.Values {
8097		if w == v {
8098			break
8099		}
8100		switch w.Op {
8101		case ssa.OpArgIntReg, ssa.OpArgFloatReg:
8102			// okay
8103		default:
8104			base.Fatalf("in %s, badly placed LoweredGetClosurePtr: %v %v", v.Block.Func.Name, v.Block, v)
8105		}
8106	}
8107}
8108
8109// CheckArgReg ensures that v is in the function's entry block.
8110func CheckArgReg(v *ssa.Value) {
8111	entry := v.Block.Func.Entry
8112	if entry != v.Block {
8113		base.Fatalf("in %s, badly placed ArgIReg or ArgFReg: %v %v", v.Block.Func.Name, v.Block, v)
8114	}
8115}
8116
8117func AddrAuto(a *obj.Addr, v *ssa.Value) {
8118	n, off := ssa.AutoVar(v)
8119	a.Type = obj.TYPE_MEM
8120	a.Sym = n.Linksym()
8121	a.Reg = int16(Arch.REGSP)
8122	a.Offset = n.FrameOffset() + off
8123	if n.Class == ir.PPARAM || (n.Class == ir.PPARAMOUT && !n.IsOutputParamInRegisters()) {
8124		a.Name = obj.NAME_PARAM
8125	} else {
8126		a.Name = obj.NAME_AUTO
8127	}
8128}
8129
8130// Call returns a new CALL instruction for the SSA value v.
8131// It uses PrepareCall to prepare the call.
8132func (s *State) Call(v *ssa.Value) *obj.Prog {
8133	pPosIsStmt := s.pp.Pos.IsStmt() // The statement-ness fo the call comes from ssaGenState
8134	s.PrepareCall(v)
8135
8136	p := s.Prog(obj.ACALL)
8137	if pPosIsStmt == src.PosIsStmt {
8138		p.Pos = v.Pos.WithIsStmt()
8139	} else {
8140		p.Pos = v.Pos.WithNotStmt()
8141	}
8142	if sym, ok := v.Aux.(*ssa.AuxCall); ok && sym.Fn != nil {
8143		p.To.Type = obj.TYPE_MEM
8144		p.To.Name = obj.NAME_EXTERN
8145		p.To.Sym = sym.Fn
8146	} else {
8147		// TODO(mdempsky): Can these differences be eliminated?
8148		switch Arch.LinkArch.Family {
8149		case sys.AMD64, sys.I386, sys.PPC64, sys.RISCV64, sys.S390X, sys.Wasm:
8150			p.To.Type = obj.TYPE_REG
8151		case sys.ARM, sys.ARM64, sys.Loong64, sys.MIPS, sys.MIPS64:
8152			p.To.Type = obj.TYPE_MEM
8153		default:
8154			base.Fatalf("unknown indirect call family")
8155		}
8156		p.To.Reg = v.Args[0].Reg()
8157	}
8158	return p
8159}
8160
8161// TailCall returns a new tail call instruction for the SSA value v.
8162// It is like Call, but for a tail call.
8163func (s *State) TailCall(v *ssa.Value) *obj.Prog {
8164	p := s.Call(v)
8165	p.As = obj.ARET
8166	return p
8167}
8168
8169// PrepareCall prepares to emit a CALL instruction for v and does call-related bookkeeping.
8170// It must be called immediately before emitting the actual CALL instruction,
8171// since it emits PCDATA for the stack map at the call (calls are safe points).
8172func (s *State) PrepareCall(v *ssa.Value) {
8173	idx := s.livenessMap.Get(v)
8174	if !idx.StackMapValid() {
8175		// See Liveness.hasStackMap.
8176		if sym, ok := v.Aux.(*ssa.AuxCall); !ok || !(sym.Fn == ir.Syms.WBZero || sym.Fn == ir.Syms.WBMove) {
8177			base.Fatalf("missing stack map index for %v", v.LongString())
8178		}
8179	}
8180
8181	call, ok := v.Aux.(*ssa.AuxCall)
8182
8183	if ok {
8184		// Record call graph information for nowritebarrierrec
8185		// analysis.
8186		if nowritebarrierrecCheck != nil {
8187			nowritebarrierrecCheck.recordCall(s.pp.CurFunc, call.Fn, v.Pos)
8188		}
8189	}
8190
8191	if s.maxarg < v.AuxInt {
8192		s.maxarg = v.AuxInt
8193	}
8194}
8195
8196// UseArgs records the fact that an instruction needs a certain amount of
8197// callee args space for its use.
8198func (s *State) UseArgs(n int64) {
8199	if s.maxarg < n {
8200		s.maxarg = n
8201	}
8202}
8203
8204// fieldIdx finds the index of the field referred to by the ODOT node n.
8205func fieldIdx(n *ir.SelectorExpr) int {
8206	t := n.X.Type()
8207	if !t.IsStruct() {
8208		panic("ODOT's LHS is not a struct")
8209	}
8210
8211	for i, f := range t.Fields() {
8212		if f.Sym == n.Sel {
8213			if f.Offset != n.Offset() {
8214				panic("field offset doesn't match")
8215			}
8216			return i
8217		}
8218	}
8219	panic(fmt.Sprintf("can't find field in expr %v\n", n))
8220
8221	// TODO: keep the result of this function somewhere in the ODOT Node
8222	// so we don't have to recompute it each time we need it.
8223}
8224
8225// ssafn holds frontend information about a function that the backend is processing.
8226// It also exports a bunch of compiler services for the ssa backend.
8227type ssafn struct {
8228	curfn      *ir.Func
8229	strings    map[string]*obj.LSym // map from constant string to data symbols
8230	stksize    int64                // stack size for current frame
8231	stkptrsize int64                // prefix of stack containing pointers
8232
8233	// alignment for current frame.
8234	// NOTE: when stkalign > PtrSize, currently this only ensures the offsets of
8235	// objects in the stack frame are aligned. The stack pointer is still aligned
8236	// only PtrSize.
8237	stkalign int64
8238
8239	log bool // print ssa debug to the stdout
8240}
8241
8242// StringData returns a symbol which
8243// is the data component of a global string constant containing s.
8244func (e *ssafn) StringData(s string) *obj.LSym {
8245	if aux, ok := e.strings[s]; ok {
8246		return aux
8247	}
8248	if e.strings == nil {
8249		e.strings = make(map[string]*obj.LSym)
8250	}
8251	data := staticdata.StringSym(e.curfn.Pos(), s)
8252	e.strings[s] = data
8253	return data
8254}
8255
8256// SplitSlot returns a slot representing the data of parent starting at offset.
8257func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t *types.Type) ssa.LocalSlot {
8258	node := parent.N
8259
8260	if node.Class != ir.PAUTO || node.Addrtaken() {
8261		// addressed things and non-autos retain their parents (i.e., cannot truly be split)
8262		return ssa.LocalSlot{N: node, Type: t, Off: parent.Off + offset}
8263	}
8264
8265	sym := &types.Sym{Name: node.Sym().Name + suffix, Pkg: types.LocalPkg}
8266	n := e.curfn.NewLocal(parent.N.Pos(), sym, t)
8267	n.SetUsed(true)
8268	n.SetEsc(ir.EscNever)
8269	types.CalcSize(t)
8270	return ssa.LocalSlot{N: n, Type: t, Off: 0, SplitOf: parent, SplitOffset: offset}
8271}
8272
8273// Logf logs a message from the compiler.
8274func (e *ssafn) Logf(msg string, args ...interface{}) {
8275	if e.log {
8276		fmt.Printf(msg, args...)
8277	}
8278}
8279
8280func (e *ssafn) Log() bool {
8281	return e.log
8282}
8283
8284// Fatalf reports a compiler error and exits.
8285func (e *ssafn) Fatalf(pos src.XPos, msg string, args ...interface{}) {
8286	base.Pos = pos
8287	nargs := append([]interface{}{ir.FuncName(e.curfn)}, args...)
8288	base.Fatalf("'%s': "+msg, nargs...)
8289}
8290
8291// Warnl reports a "warning", which is usually flag-triggered
8292// logging output for the benefit of tests.
8293func (e *ssafn) Warnl(pos src.XPos, fmt_ string, args ...interface{}) {
8294	base.WarnfAt(pos, fmt_, args...)
8295}
8296
8297func (e *ssafn) Debug_checknil() bool {
8298	return base.Debug.Nil != 0
8299}
8300
8301func (e *ssafn) UseWriteBarrier() bool {
8302	return base.Flag.WB
8303}
8304
8305func (e *ssafn) Syslook(name string) *obj.LSym {
8306	switch name {
8307	case "goschedguarded":
8308		return ir.Syms.Goschedguarded
8309	case "writeBarrier":
8310		return ir.Syms.WriteBarrier
8311	case "wbZero":
8312		return ir.Syms.WBZero
8313	case "wbMove":
8314		return ir.Syms.WBMove
8315	case "cgoCheckMemmove":
8316		return ir.Syms.CgoCheckMemmove
8317	case "cgoCheckPtrWrite":
8318		return ir.Syms.CgoCheckPtrWrite
8319	}
8320	e.Fatalf(src.NoXPos, "unknown Syslook func %v", name)
8321	return nil
8322}
8323
8324func (e *ssafn) Func() *ir.Func {
8325	return e.curfn
8326}
8327
8328func clobberBase(n ir.Node) ir.Node {
8329	if n.Op() == ir.ODOT {
8330		n := n.(*ir.SelectorExpr)
8331		if n.X.Type().NumFields() == 1 {
8332			return clobberBase(n.X)
8333		}
8334	}
8335	if n.Op() == ir.OINDEX {
8336		n := n.(*ir.IndexExpr)
8337		if n.X.Type().IsArray() && n.X.Type().NumElem() == 1 {
8338			return clobberBase(n.X)
8339		}
8340	}
8341	return n
8342}
8343
8344// callTargetLSym returns the correct LSym to call 'callee' using its ABI.
8345func callTargetLSym(callee *ir.Name) *obj.LSym {
8346	if callee.Func == nil {
8347		// TODO(austin): This happens in case of interface method I.M from imported package.
8348		// It's ABIInternal, and would be better if callee.Func was never nil and we didn't
8349		// need this case.
8350		return callee.Linksym()
8351	}
8352
8353	return callee.LinksymABI(callee.Func.ABI)
8354}
8355
8356func min8(a, b int8) int8 {
8357	if a < b {
8358		return a
8359	}
8360	return b
8361}
8362
8363func max8(a, b int8) int8 {
8364	if a > b {
8365		return a
8366	}
8367	return b
8368}
8369
8370// deferStructFnField is the field index of _defer.fn.
8371const deferStructFnField = 4
8372
8373var deferType *types.Type
8374
8375// deferstruct returns a type interchangeable with runtime._defer.
8376// Make sure this stays in sync with runtime/runtime2.go:_defer.
8377func deferstruct() *types.Type {
8378	if deferType != nil {
8379		return deferType
8380	}
8381
8382	makefield := func(name string, t *types.Type) *types.Field {
8383		sym := (*types.Pkg)(nil).Lookup(name)
8384		return types.NewField(src.NoXPos, sym, t)
8385	}
8386
8387	fields := []*types.Field{
8388		makefield("heap", types.Types[types.TBOOL]),
8389		makefield("rangefunc", types.Types[types.TBOOL]),
8390		makefield("sp", types.Types[types.TUINTPTR]),
8391		makefield("pc", types.Types[types.TUINTPTR]),
8392		// Note: the types here don't really matter. Defer structures
8393		// are always scanned explicitly during stack copying and GC,
8394		// so we make them uintptr type even though they are real pointers.
8395		makefield("fn", types.Types[types.TUINTPTR]),
8396		makefield("link", types.Types[types.TUINTPTR]),
8397		makefield("head", types.Types[types.TUINTPTR]),
8398	}
8399	if name := fields[deferStructFnField].Sym.Name; name != "fn" {
8400		base.Fatalf("deferStructFnField is %q, not fn", name)
8401	}
8402
8403	n := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.Pkgs.Runtime.Lookup("_defer"))
8404	typ := types.NewNamed(n)
8405	n.SetType(typ)
8406	n.SetTypecheck(1)
8407
8408	// build struct holding the above fields
8409	typ.SetUnderlying(types.NewStruct(fields))
8410	types.CalcStructSize(typ)
8411
8412	deferType = typ
8413	return typ
8414}
8415
8416// SpillSlotAddr uses LocalSlot information to initialize an obj.Addr
8417// The resulting addr is used in a non-standard context -- in the prologue
8418// of a function, before the frame has been constructed, so the standard
8419// addressing for the parameters will be wrong.
8420func SpillSlotAddr(spill ssa.Spill, baseReg int16, extraOffset int64) obj.Addr {
8421	return obj.Addr{
8422		Name:   obj.NAME_NONE,
8423		Type:   obj.TYPE_MEM,
8424		Reg:    baseReg,
8425		Offset: spill.Offset + extraOffset,
8426	}
8427}
8428
8429var (
8430	BoundsCheckFunc [ssa.BoundsKindCount]*obj.LSym
8431	ExtendCheckFunc [ssa.BoundsKindCount]*obj.LSym
8432)
8433