@@ -209,7 +209,11 @@ func genRules(arch arch) {
209
209
210
210
canFail = false
211
211
fmt .Fprintf (buf , "for {\n " )
212
- if genMatch (buf , arch , match , rule .loc ) {
212
+ pos , matchCanFail := genMatch (buf , arch , match , rule .loc )
213
+ if pos == "" {
214
+ pos = "v.Pos"
215
+ }
216
+ if matchCanFail {
213
217
canFail = true
214
218
}
215
219
@@ -221,7 +225,7 @@ func genRules(arch arch) {
221
225
log .Fatalf ("unconditional rule %s is followed by other rules" , match )
222
226
}
223
227
224
- genResult (buf , arch , result , rule .loc )
228
+ genResult (buf , arch , result , rule .loc , pos )
225
229
if * genLog {
226
230
fmt .Fprintf (buf , "logRule(\" %s\" )\n " , rule .loc )
227
231
}
@@ -291,10 +295,11 @@ func genRules(arch arch) {
291
295
_ , _ , _ , aux , s := extract (match ) // remove parens, then split
292
296
293
297
// check match of control value
298
+ pos := ""
294
299
if s [0 ] != "nil" {
295
300
fmt .Fprintf (w , "v := b.Control\n " )
296
301
if strings .Contains (s [0 ], "(" ) {
297
- genMatch0 (w , arch , s [0 ], "v" , map [string ]struct {}{}, false , rule .loc )
302
+ pos , _ = genMatch0 (w , arch , s [0 ], "v" , map [string ]struct {}{}, false , rule .loc )
298
303
} else {
299
304
fmt .Fprintf (w , "_ = v\n " ) // in case we don't use v
300
305
fmt .Fprintf (w , "%s := b.Control\n " , s [0 ])
@@ -335,7 +340,10 @@ func genRules(arch arch) {
335
340
if t [0 ] == "nil" {
336
341
fmt .Fprintf (w , "b.SetControl(nil)\n " )
337
342
} else {
338
- fmt .Fprintf (w , "b.SetControl(%s)\n " , genResult0 (w , arch , t [0 ], new (int ), false , false , rule .loc ))
343
+ if pos == "" {
344
+ pos = "v.Pos"
345
+ }
346
+ fmt .Fprintf (w , "b.SetControl(%s)\n " , genResult0 (w , arch , t [0 ], new (int ), false , false , rule .loc , pos ))
339
347
}
340
348
if aux != "" {
341
349
fmt .Fprintf (w , "b.Aux = %s\n " , aux )
@@ -386,15 +394,17 @@ func genRules(arch arch) {
386
394
}
387
395
}
388
396
389
- // genMatch reports whether the match can fail.
390
- func genMatch (w io.Writer , arch arch , match string , loc string ) bool {
397
+ // genMatch returns the variable whose source position should be used for the
398
+ // result (or "" if no opinion), and a boolean that reports whether the match can fail.
399
+ func genMatch (w io.Writer , arch arch , match string , loc string ) (string , bool ) {
391
400
return genMatch0 (w , arch , match , "v" , map [string ]struct {}{}, true , loc )
392
401
}
393
402
394
- func genMatch0 (w io.Writer , arch arch , match , v string , m map [string ]struct {}, top bool , loc string ) bool {
403
+ func genMatch0 (w io.Writer , arch arch , match , v string , m map [string ]struct {}, top bool , loc string ) ( string , bool ) {
395
404
if match [0 ] != '(' || match [len (match )- 1 ] != ')' {
396
405
panic ("non-compound expr in genMatch0: " + match )
397
406
}
407
+ pos := ""
398
408
canFail := false
399
409
400
410
op , oparch , typ , auxint , aux , args := parseValue (match , arch , loc )
@@ -404,6 +414,10 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, t
404
414
fmt .Fprintf (w , "if %s.Op != Op%s%s {\n break\n }\n " , v , oparch , op .name )
405
415
canFail = true
406
416
}
417
+ if op .faultOnNilArg0 || op .faultOnNilArg1 {
418
+ // Prefer the position of an instruction which could fault.
419
+ pos = v + ".Pos"
420
+ }
407
421
408
422
if typ != "" {
409
423
if ! isVariable (typ ) {
@@ -494,7 +508,16 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, t
494
508
argname = fmt .Sprintf ("%s_%d" , v , i )
495
509
}
496
510
fmt .Fprintf (w , "%s := %s.Args[%d]\n " , argname , v , i )
497
- if genMatch0 (w , arch , arg , argname , m , false , loc ) {
511
+ argPos , argCanFail := genMatch0 (w , arch , arg , argname , m , false , loc )
512
+ if argPos != "" {
513
+ // Keep the argument in preference to the parent, as the
514
+ // argument is normally earlier in program flow.
515
+ // Keep the argument in preference to an earlier argument,
516
+ // as that prefers the memory argument which is also earlier
517
+ // in the program flow.
518
+ pos = argPos
519
+ }
520
+ if argCanFail {
498
521
canFail = true
499
522
}
500
523
}
@@ -503,10 +526,10 @@ func genMatch0(w io.Writer, arch arch, match, v string, m map[string]struct{}, t
503
526
fmt .Fprintf (w , "if len(%s.Args) != %d {\n break\n }\n " , v , len (args ))
504
527
canFail = true
505
528
}
506
- return canFail
529
+ return pos , canFail
507
530
}
508
531
509
- func genResult (w io.Writer , arch arch , result string , loc string ) {
532
+ func genResult (w io.Writer , arch arch , result string , loc string , pos string ) {
510
533
move := false
511
534
if result [0 ] == '@' {
512
535
// parse @block directive
@@ -515,9 +538,9 @@ func genResult(w io.Writer, arch arch, result string, loc string) {
515
538
result = s [1 ]
516
539
move = true
517
540
}
518
- genResult0 (w , arch , result , new (int ), true , move , loc )
541
+ genResult0 (w , arch , result , new (int ), true , move , loc , pos )
519
542
}
520
- func genResult0 (w io.Writer , arch arch , result string , alloc * int , top , move bool , loc string ) string {
543
+ func genResult0 (w io.Writer , arch arch , result string , alloc * int , top , move bool , loc string , pos string ) string {
521
544
// TODO: when generating a constant result, use f.constVal to avoid
522
545
// introducing copies just to clean them up again.
523
546
if result [0 ] != '(' {
@@ -554,7 +577,7 @@ func genResult0(w io.Writer, arch arch, result string, alloc *int, top, move boo
554
577
}
555
578
v = fmt .Sprintf ("v%d" , * alloc )
556
579
* alloc ++
557
- fmt .Fprintf (w , "%s := b.NewValue0(v.Pos , Op%s%s, %s)\n " , v , oparch , op .name , typ )
580
+ fmt .Fprintf (w , "%s := b.NewValue0(%s , Op%s%s, %s)\n " , v , pos , oparch , op .name , typ )
558
581
if move && top {
559
582
// Rewrite original into a copy
560
583
fmt .Fprintf (w , "v.reset(OpCopy)\n " )
@@ -569,7 +592,7 @@ func genResult0(w io.Writer, arch arch, result string, alloc *int, top, move boo
569
592
fmt .Fprintf (w , "%s.Aux = %s\n " , v , aux )
570
593
}
571
594
for _ , arg := range args {
572
- x := genResult0 (w , arch , arg , alloc , false , move , loc )
595
+ x := genResult0 (w , arch , arg , alloc , false , move , loc , pos )
573
596
fmt .Fprintf (w , "%s.AddArg(%s)\n " , v , x )
574
597
}
575
598
0 commit comments