| // run | |
| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // Issue 80577: on riscv64, sign extensions were elided after | |
| // 32-bit instructions that architecturally sign-extend their | |
| // result, but an unsigned-typed value spilled across a call is | |
| // restored with a zero-extending load, losing the elided | |
| // sign extension. | |
| package main | |
| import "math/bits" | |
| var sink uint32 | |
| //go:noinline | |
| func use(x uint32) { sink = x } | |
| //go:noinline | |
| func mul(a, b uint32) int64 { | |
| p := a * b | |
| use(p) // p live across the call, forcing a spill | |
| return int64(int32(p)) | |
| } | |
| //go:noinline | |
| func div(a, b uint32) int64 { | |
| p := a / b | |
| use(p) | |
| return int64(int32(p)) | |
| } | |
| //go:noinline | |
| func rem(a, b uint32) int64 { | |
| p := a % b | |
| use(p) | |
| return int64(int32(p)) | |
| } | |
| //go:noinline | |
| func rot(a uint32, k int) int64 { | |
| p := bits.RotateLeft32(a, k) | |
| use(p) | |
| return int64(int32(p)) | |
| } | |
| func main() { | |
| const want = -2147483648 | |
| if got := mul(0x8000, 0x10000); got != want { | |
| println("mul: got", got, "want", want) | |
| panic("bad mul") | |
| } | |
| if got := div(0x80000000, 1); got != want { | |
| println("div: got", got, "want", want) | |
| panic("bad div") | |
| } | |
| if got := rem(0x80000000, 0xffffffff); got != want { | |
| println("rem: got", got, "want", want) | |
| panic("bad rem") | |
| } | |
| if got := rot(1, 31); got != want { | |
| println("rot: got", got, "want", want) | |
| panic("bad rot") | |
| } | |
| } |