]> Cypherpunks.ru repositories - gostls13.git/blob - test/live_regabi.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / live_regabi.go
1 // errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
2
3 //go:build (amd64 && goexperiment.regabiargs) || (arm64 && goexperiment.regabiargs)
4
5 // Copyright 2014 The Go Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style
7 // license that can be found in the LICENSE file.
8
9 // liveness tests with inlining disabled.
10 // see also live2.go.
11
12 package main
13
14 import "runtime"
15
16 func printnl()
17
18 //go:noescape
19 func printpointer(**int)
20
21 //go:noescape
22 func printintpointer(*int)
23
24 //go:noescape
25 func printstringpointer(*string)
26
27 //go:noescape
28 func printstring(string)
29
30 //go:noescape
31 func printbytepointer(*byte)
32
33 func printint(int)
34
35 func f1() {
36         var x *int       // ERROR "stack object x \*int$"
37         printpointer(&x) // ERROR "live at call to printpointer: x$"
38         printpointer(&x)
39 }
40
41 func f2(b bool) {
42         if b {
43                 printint(0) // nothing live here
44                 return
45         }
46         var x *int       // ERROR "stack object x \*int$"
47         printpointer(&x) // ERROR "live at call to printpointer: x$"
48         printpointer(&x)
49 }
50
51 func f3(b1, b2 bool) {
52         // Here x and y are ambiguously live. In previous go versions they
53         // were marked as live throughout the function to avoid being
54         // poisoned in GODEBUG=gcdead=1 mode; this is now no longer the
55         // case.
56
57         printint(0)
58         if b1 == false {
59                 printint(0)
60                 return
61         }
62
63         if b2 {
64                 var x *int       // ERROR "stack object x \*int$"
65                 printpointer(&x) // ERROR "live at call to printpointer: x$"
66                 printpointer(&x)
67         } else {
68                 var y *int       // ERROR "stack object y \*int$"
69                 printpointer(&y) // ERROR "live at call to printpointer: y$"
70                 printpointer(&y)
71         }
72         printint(0) // nothing is live here
73 }
74
75 // The old algorithm treated x as live on all code that
76 // could flow to a return statement, so it included the
77 // function entry and code above the declaration of x
78 // but would not include an indirect use of x in an infinite loop.
79 // Check that these cases are handled correctly.
80
81 func f4(b1, b2 bool) { // x not live here
82         if b2 {
83                 printint(0) // x not live here
84                 return
85         }
86         var z **int
87         x := new(int) // ERROR "stack object x \*int$"
88         *x = 42
89         z = &x
90         printint(**z) // ERROR "live at call to printint: x$"
91         if b2 {
92                 printint(1) // x not live here
93                 return
94         }
95         for {
96                 printint(**z) // ERROR "live at call to printint: x$"
97         }
98 }
99
100 func f5(b1 bool) {
101         var z **int
102         if b1 {
103                 x := new(int) // ERROR "stack object x \*int$"
104                 *x = 42
105                 z = &x
106         } else {
107                 y := new(int) // ERROR "stack object y \*int$"
108                 *y = 54
109                 z = &y
110         }
111         printint(**z) // nothing live here
112 }
113
114 // confusion about the _ result used to cause spurious "live at entry to f6: _".
115
116 func f6() (_, y string) {
117         y = "hello"
118         return
119 }
120
121 // confusion about addressed results used to cause "live at entry to f7: x".
122
123 func f7() (x string) { // ERROR "stack object x string"
124         _ = &x
125         x = "hello"
126         return
127 }
128
129 // ignoring block returns used to cause "live at entry to f8: x, y".
130
131 func f8() (x, y string) {
132         return g8()
133 }
134
135 func g8() (string, string)
136
137 // ignoring block assignments used to cause "live at entry to f9: x"
138 // issue 7205
139
140 var i9 interface{}
141
142 func f9() bool {
143         g8()
144         x := i9
145         y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$"
146         i9 = y                  // make y escape so the line above has to call convT
147         return x != y
148 }
149
150 // liveness formerly confused by UNDEF followed by RET,
151 // leading to "live at entry to f10: ~r1" (unnamed result).
152
153 func f10() string {
154         panic(1)
155 }
156
157 // liveness formerly confused by select, thinking runtime.selectgo
158 // can return to next instruction; it always jumps elsewhere.
159 // note that you have to use at least two cases in the select
160 // to get a true select; smaller selects compile to optimized helper functions.
161
162 var c chan *int
163 var b bool
164
165 // this used to have a spurious "live at entry to f11a: ~r0"
166 func f11a() *int {
167         select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
168         case <-c:
169                 return nil
170         case <-c:
171                 return nil
172         }
173 }
174
175 func f11b() *int {
176         p := new(int)
177         if b {
178                 // At this point p is dead: the code here cannot
179                 // get to the bottom of the function.
180                 // This used to have a spurious "live at call to printint: p".
181                 printint(1) // nothing live here!
182                 select {    // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
183                 case <-c:
184                         return nil
185                 case <-c:
186                         return nil
187                 }
188         }
189         println(*p)
190         return nil
191 }
192
193 var sink *int
194
195 func f11c() *int {
196         p := new(int)
197         sink = p // prevent stack allocation, otherwise p is rematerializeable
198         if b {
199                 // Unlike previous, the cases in this select fall through,
200                 // so we can get to the println, so p is not dead.
201                 printint(1) // ERROR "live at call to printint: p$"
202                 select {    // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
203                 case <-c:
204                 case <-c:
205                 }
206         }
207         println(*p)
208         return nil
209 }
210
211 // similarly, select{} does not fall through.
212 // this used to have a spurious "live at entry to f12: ~r0".
213
214 func f12() *int {
215         if b {
216                 select {}
217         } else {
218                 return nil
219         }
220 }
221
222 // incorrectly placed VARDEF annotations can cause missing liveness annotations.
223 // this used to be missing the fact that s is live during the call to g13 (because it is
224 // needed for the call to h13).
225
226 func f13() {
227         s := g14()
228         s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$"
229 }
230
231 func g13(string) string
232 func h13(string, string) string
233
234 // more incorrectly placed VARDEF.
235
236 func f14() {
237         x := g14() // ERROR "stack object x string$"
238         printstringpointer(&x)
239 }
240
241 func g14() string
242
243 // Checking that various temporaries do not persist or cause
244 // ambiguously live values that must be zeroed.
245 // The exact temporary names are inconsequential but we are
246 // trying to check that there is only one at any given site,
247 // and also that none show up in "ambiguously live" messages.
248
249 var m map[string]int
250 var mi map[interface{}]int
251
252 // str and iface are used to ensure that a temp is required for runtime calls below.
253 func str() string
254 func iface() interface{}
255
256 func f16() {
257         if b {
258                 delete(mi, iface()) // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
259         }
260         delete(mi, iface())
261         delete(mi, iface())
262 }
263
264 var m2s map[string]*byte
265 var m2 map[[2]string]*byte
266 var x2 [2]string
267 var bp *byte
268
269 func f17a(p *byte) { // ERROR "live at entry to f17a: p$"
270         if b {
271                 m2[x2] = p // ERROR "live at call to mapassign: p$"
272         }
273         m2[x2] = p // ERROR "live at call to mapassign: p$"
274         m2[x2] = p // ERROR "live at call to mapassign: p$"
275 }
276
277 func f17b(p *byte) { // ERROR "live at entry to f17b: p$"
278         // key temporary
279         if b {
280                 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
281         }
282         m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
283         m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
284 }
285
286 func f17c() {
287         // key and value temporaries
288         if b {
289                 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
290         }
291         m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
292         m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
293 }
294
295 func f17d() *byte
296
297 func g18() [2]string
298
299 func f18() {
300         // key temporary for mapaccess.
301         // temporary introduced by orderexpr.
302         var z *byte
303         if b {
304                 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
305         }
306         z = m2[g18()]
307         z = m2[g18()]
308         printbytepointer(z)
309 }
310
311 var ch chan *byte
312
313 // byteptr is used to ensure that a temp is required for runtime calls below.
314 func byteptr() *byte
315
316 func f19() {
317         // dest temporary for channel receive.
318         var z *byte
319
320         if b {
321                 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$"
322         }
323         z = <-ch
324         z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$"
325         printbytepointer(z)
326 }
327
328 func f20() {
329         // src temporary for channel send
330         if b {
331                 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$"
332         }
333         ch <- byteptr()
334         ch <- byteptr()
335 }
336
337 func f21() {
338         // key temporary for mapaccess using array literal key.
339         var z *byte
340         if b {
341                 z = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
342         }
343         z = m2[[2]string{"x", "y"}]
344         z = m2[[2]string{"x", "y"}]
345         printbytepointer(z)
346 }
347
348 func f23() {
349         // key temporary for two-result map access using array literal key.
350         var z *byte
351         var ok bool
352         if b {
353                 z, ok = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
354         }
355         z, ok = m2[[2]string{"x", "y"}]
356         z, ok = m2[[2]string{"x", "y"}]
357         printbytepointer(z)
358         print(ok)
359 }
360
361 func f24() {
362         // key temporary for map access using array literal key.
363         // value temporary too.
364         if b {
365                 m2[[2]string{"x", "y"}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
366         }
367         m2[[2]string{"x", "y"}] = nil
368         m2[[2]string{"x", "y"}] = nil
369 }
370
371 // Non-open-coded defers should not cause autotmps.  (Open-coded defers do create extra autotmps).
372 func f25(b bool) {
373         for i := 0; i < 2; i++ {
374                 // Put in loop to make sure defer is not open-coded
375                 defer g25()
376         }
377         if b {
378                 return
379         }
380         var x string
381         x = g14()
382         printstring(x)
383         return
384 }
385
386 func g25()
387
388 // non-escaping ... slices passed to function call should die on return,
389 // so that the temporaries do not stack and do not cause ambiguously
390 // live variables.
391
392 func f26(b bool) {
393         if b {
394                 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$"
395         }
396         print26((*int)(nil), (*int)(nil), (*int)(nil))
397         print26((*int)(nil), (*int)(nil), (*int)(nil))
398         printnl()
399 }
400
401 //go:noescape
402 func print26(...interface{})
403
404 // non-escaping closures passed to function call should die on return
405
406 func f27(b bool) {
407         x := 0
408         if b {
409                 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
410         }
411         call27(func() { x++ })
412         call27(func() { x++ })
413         printnl()
414 }
415
416 // but defer does escape to later execution in the function
417
418 func f27defer(b bool) {
419         x := 0
420         if b {
421                 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
422         }
423         defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
424         printnl()                    // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+"
425         return                       // ERROR "live at indirect call: .autotmp_[0-9]+"
426 }
427
428 // and newproc (go) escapes to the heap
429
430 func f27go(b bool) {
431         x := 0
432         if b {
433                 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: &x .autotmp_[0-9]+$" "live at call to newproc: &x$" // allocate two closures, the func literal, and the wrapper for go
434         }
435         go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: .autotmp_[0-9]+$" // allocate two closures, the func literal, and the wrapper for go
436         printnl()
437 }
438
439 //go:noescape
440 func call27(func())
441
442 // concatstring slice should die on return
443
444 var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
445
446 func f28(b bool) {
447         if b {
448                 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$"
449         }
450         printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
451         printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
452 }
453
454 // map iterator should die on end of range loop
455
456 func f29(b bool) {
457         if b {
458                 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hiter$"
459                         printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
460                 }
461         }
462         for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$"
463                 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
464         }
465         for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$"
466                 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
467         }
468 }
469
470 // copy of array of pointers should die at end of range loop
471 var pstructarr [10]pstruct
472
473 // Struct size chosen to make pointer to element in pstructarr
474 // not computable by strength reduction.
475 type pstruct struct {
476         intp *int
477         _    [8]byte
478 }
479
480 func f30(b bool) {
481         // live temp during printintpointer(p):
482         // the internal iterator pointer if a pointer to pstruct in pstructarr
483         // can not be easily computed by strength reduction.
484         if b {
485                 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$"
486                         printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
487                 }
488         }
489         for _, p := range pstructarr {
490                 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
491         }
492         for _, p := range pstructarr {
493                 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
494         }
495 }
496
497 // conversion to interface should not leave temporary behind
498
499 func f31(b1, b2, b3 bool) {
500         if b1 {
501                 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
502         }
503         if b2 {
504                 h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
505         }
506         if b3 {
507                 panic(g18())
508         }
509         print(b3)
510 }
511
512 func g31(interface{})
513 func h31(...interface{})
514
515 // non-escaping partial functions passed to function call should die on return
516
517 type T32 int
518
519 func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$"
520         *t++
521 }
522
523 var t32 T32
524
525 func f32(b bool) {
526         if b {
527                 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{"
528         }
529         call32(t32.Inc)
530         call32(t32.Inc)
531 }
532
533 //go:noescape
534 func call32(func())
535
536 // temporaries introduced during if conditions and && || expressions
537 // should die once the condition has been acted upon.
538
539 var m33 map[interface{}]int
540
541 func f33() {
542         if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
543                 printnl()
544                 return
545         } else {
546                 printnl()
547         }
548         printnl()
549 }
550
551 func f34() {
552         if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
553                 printnl()
554                 return
555         }
556         printnl()
557 }
558
559 func f35() {
560         if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
561                 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
562                 printnl()
563                 return
564         }
565         printnl()
566 }
567
568 func f36() {
569         if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
570                 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
571                 printnl()
572                 return
573         }
574         printnl()
575 }
576
577 func f37() {
578         if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
579                 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
580                 m33[byteptr()] == 0 {
581                 printnl()
582                 return
583         }
584         printnl()
585 }
586
587 // select temps should disappear in the case bodies
588
589 var c38 chan string
590
591 func fc38() chan string
592 func fi38(int) *string
593 func fb38() *bool
594
595 func f38(b bool) {
596         // we don't care what temps are printed on the lines with output.
597         // we care that the println lines have no live variables
598         // and therefore no output.
599         if b {
600                 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]runtime.scase$"
601                 case <-fc38():
602                         printnl()
603                 case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
604                         printnl()
605                 case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
606                         printnl()
607                 case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$"
608                         printnl()
609                 }
610                 printnl()
611         }
612         printnl()
613 }
614
615 // issue 8097: mishandling of x = x during return.
616
617 func f39() (x []int) {
618         x = []int{1}
619         printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
620         return x
621 }
622
623 func f39a() (x []int) {
624         x = []int{1}
625         printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
626         return
627 }
628
629 func f39b() (x [10]*int) {
630         x = [10]*int{}
631         x[0] = new(int) // ERROR "live at call to newobject: x$"
632         printnl()       // ERROR "live at call to printnl: x$"
633         return x
634 }
635
636 func f39c() (x [10]*int) {
637         x = [10]*int{}
638         x[0] = new(int) // ERROR "live at call to newobject: x$"
639         printnl()       // ERROR "live at call to printnl: x$"
640         return
641 }
642
643 // issue 8142: lost 'addrtaken' bit on inlined variables.
644 // no inlining in this test, so just checking that non-inlined works.
645
646 type T40 struct {
647         m map[int]int
648 }
649
650 //go:noescape
651 func useT40(*T40)
652
653 func newT40() *T40 {
654         ret := T40{}
655         ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$"
656         return &ret
657 }
658
659 func bad40() {
660         t := newT40()
661         _ = t
662         printnl()
663 }
664
665 func good40() {
666         ret := T40{}              // ERROR "stack object ret T40$"
667         ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hmap$"
668         t := &ret
669         printnl() // ERROR "live at call to printnl: ret$"
670         // Note: ret is live at the printnl because the compiler moves &ret
671         // from before the printnl to after.
672         useT40(t)
673 }
674
675 func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$"
676         ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$"
677         printnl()
678         // Note: no .?autotmp live at printnl.  See issue 16996.
679 }
680 func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$"
681         sink = a[0]
682 }
683
684 // issue 16016: autogenerated wrapper should have arguments live
685 type T struct{}
686
687 func (*T) Foo(ptr *int) {}
688
689 type R struct{ *T }
690
691 // issue 18860: output arguments must be live all the time if there is a defer.
692 // In particular, at printint r must be live.
693 func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$"
694         r = p
695         defer func() {
696                 recover()
697         }()
698         printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$"
699         r = q
700         return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$"
701 }
702
703 func f42() {
704         var p, q, r int
705         f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$"
706         f43([]*int{&p, &r, &q})
707         f43([]*int{&q, &p, &r})
708 }
709
710 //go:noescape
711 func f43(a []*int)
712
713 // Assigning to a sub-element that makes up an entire local variable
714 // should clobber that variable.
715 func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
716         type T struct {
717                 s [1][2]*int
718         }
719         ret := T{} // ERROR "stack object ret T"
720         ret.s[0] = f()
721         return ret
722 }
723
724 func f45(a, b, c, d, e, f, g, h, i, j, k, l *byte) { // ERROR "live at entry to f45: a b c d e f g h i j k l"
725         f46(a, b, c, d, e, f, g, h, i, j, k, l) // ERROR "live at call to f46: a b c d e f g h i j k l"
726         runtime.KeepAlive(a)
727         runtime.KeepAlive(b)
728         runtime.KeepAlive(c)
729         runtime.KeepAlive(d)
730         runtime.KeepAlive(e)
731         runtime.KeepAlive(f)
732         runtime.KeepAlive(g)
733         runtime.KeepAlive(h)
734         runtime.KeepAlive(i)
735         runtime.KeepAlive(j)
736         runtime.KeepAlive(k)
737         runtime.KeepAlive(l)
738 }
739
740 //go:noinline
741 func f46(a, b, c, d, e, f, g, h, i, j, k, l *byte) {
742 }